1

우리는 사용자가 Active Directory 자격 증명을 사용하여 로그인하게하려는 grails 응용 프로그램을 만들고 있습니다. 또한이 애플리케이션의 비즈니스 소유자에게 특정 링크 (작업)에 대한 액세스 권한을 가진 사용자를 제어 할 수있는 권한을 부여하고자합니다. 우리가 비즈니스 사용자에게 권한을 부여 할 때문에Grails의 Spring Security가 생성 한 PERSON 테이블에 LDAP 사용자를 통합하는 방법은 무엇입니까?

  1. 스프링 시큐리티 코어
  2. 봄 보안 LDAP
  3. 봄 보안 UI

:이 때문에 우리는 우리의 Grails 애플리케이션에서 다음과 같은 플러그인을 사용하는 필요한 경우 특정 권한 (작업)을 가진 사용자 정의 된 역할을 즉각적으로 작성하십시오. 우리는 최상의 스프링 보안 구성이 Requestmap 데이터베이스 기반 접근 방식이라고 생각합니다.

다음과 같이

은 지금까지 우리가 달성 한 :

  • 우리는 성공적으로 Active Directory에 대해 인증 할 수있는된다.
  • 우리는 또한 스프링 보안 UI 플러그인의 UI 인터페이스를 통해 다른 역할 (ROLE_XXX)에 대한 다른 요청 매핑을 만들

문제/질문

스프링 보안 할 수 있었다

  • PERSON
  • AUTHORITY
  • : -core 플러그인은 다음과 같은 테이블을 생성
  • PERSON_AUTHORITY
  • REQUESTMAP

이러한 역할의 생성, 역할에 대한 URL의 할당을 지원하는 테이블입니다. 그러나 관례 이름 인 Person_Authority 테이블은 개인이 잠재적으로 둘 이상의 역할을 가질 수 있기 때문에 PERSON과 AUTHORITY (ROLE) 사이에 많은 관계가 있음을 의미합니다. 내 문제는 사람이 이미 Active Directory (외부 소스)에 있고 응용 프로그램에서 만들어지지 않았기 때문에 사람이 없다는 것입니다.

인증 된 사용자를 PERSON으로 만드는 방법이 있습니까? 스프링 보안 솔루션은 사용자 행이나 객체를 요구하지만 참조 할 수 있습니다.

는 또한 여기에 질문을 게시 한 :

http://grails.1312388.n4.nabble.com/Issues-integrating-LDAP-Authentication-with-Requestmap-to-Secure-URLs-td4644040.html

감사합니다,

+1

우리가 한 일이다. 우리는 사용자가 LDAP에 대해 인증 받았던 것과 비슷한 상황을 겪었습니다. 결국 우리가 한 사람이 LDAP에 대해 인증되면 Persons 테이블에서 그를 찾았습니다. 존재하지 않으면 우리는 기본 정보를 가지고 그를 생성 한 다음 해당 객체를 RequestMap에 추가하십시오. 그 사람이 Persons 테이블에 이미 존재했다면 우리는 그를 추가하지 않지만 핵심 부분은 두 경우 모두 사용자가 여전히 LDAP에 대해 인증되고 있다는 것입니다. – allthenutsandbolts

+0

@allthenutsandbolts 성공하지 못했습니다. 암호 필드는 사람을 생성하는 사용자/저장 작업에 j_password 필드를 전달하는 필수 필드입니다. j_security_check에 로그인을 게시 할 때 사용자 레코드를 삽입하기 위해 더 이상 자격 증명에 액세스 할 필요가 없습니다. 나는 수동으로 Person 테이블을 만들려고했는데, LDAP를 통해 인증하는 동안 Spring 보안 UI를 통해 수동으로 만들려고했지만 보안 URL로 갔을 때 작동하지 않았다. 사용자 테이블과 사용자 테이블 사이의 연결이 끊어지는 것처럼 보였다. LDAP의 사용자 또는 어쩌면 무언가가 등록 또는 초기화되지 않았습니다. – Viriato

+0

원하는 비밀번호로 설정할 수 있습니다. 인증에 사용하지 않을 것입니다. 맞습니다. j_password 필드에 대한 액세스 권한이 없습니다. – allthenutsandbolts

답변

6

그래서 당신은 기본적으로 사람에 AD 사용자를 매핑해야합니다.

다음은 src/groovy에서 필요한 3 가지 클래스입니다. 필요에 따라 분명히 수정하십시오.

package yourpackagename 

    import org.codehaus.groovy.grails.plugins.springsecurity.GrailsUser 
    import org.springframework.security.core.GrantedAuthority 

    class CustomUserDetails extends GrailsUser{ 
     final String firstName 
     final String lastName 

     CustomUserDetails(String username, String password, boolean enabled, 
          boolean accountNonExpired, boolean credentialsNonExpired, 
          boolean accountNonLocked, 
          Collection<GrantedAuthority> authorities, 
          long id, String firstName, String lastName) { 
      super(username, password, enabled, accountNonExpired, 
        credentialsNonExpired, accountNonLocked, authorities, id) 

      this.firstName = firstName 
      this.lastName = lastName 
     } 
    } 

package yourpackagenamehere 

import org.codehaus.groovy.grails.plugins.springsecurity.GrailsUserDetailsService 
import org.springframework.security.core.authority.GrantedAuthorityImpl 
import org.springframework.security.core.userdetails.UserDetails 
import org.springframework.security.core.userdetails.UsernameNotFoundException 
import org.codehaus.groovy.grails.plugins.springsecurity.SpringSecurityUtils 

class CustomUserDetailsService implements GrailsUserDetailsService { 

    /** 
    * Some Spring Security classes (e.g. RoleHierarchyVoter) expect at least one role, so 
    * we give a user with no granted roles this one which gets past that restriction but 
    * doesn't grant anything. 
    */ 
    static final List NO_ROLES = [new GrantedAuthorityImpl(SpringSecurityUtils.NO_ROLE)] 

    UserDetails loadUserByUsername(String username, boolean loadRoles) 
    throws UsernameNotFoundException { 
     return loadUserByUsername(username) 
    } 

    UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { 

     User.withTransaction { status -> 

      User user = User.findByUsername(username) 
      if (!user) throw new UsernameNotFoundException('User not found', username) 

      def authorities = user.authorities.collect {new GrantedAuthorityImpl(it.authority)} 

      return new CustomUserDetails(user.username, user.password, user.enabled, 
        !user.accountExpired, !user.passwordExpired, 
        !user.accountLocked, authorities ?: NO_ROLES, user.id, 
        user.firstName, user.lastName) 
     } as UserDetails 
    } 
} 

package yourpackagenamehere 

import groovy.sql.Sql 

import org.springframework.ldap.core.DirContextAdapter 
import org.springframework.ldap.core.DirContextOperations 
import org.springframework.security.core.userdetails.UserDetails 
import org.springframework.security.ldap.userdetails.UserDetailsContextMapper 
import org.springframework.security.core.authority.GrantedAuthorityImpl 
import org.springframework.security.core.GrantedAuthority 
import org.codehaus.groovy.grails.plugins.springsecurity.SpringSecurityUtils 

import org.springframework.security.core.userdetails.UsernameNotFoundException 
import org.springframework.security.authentication.DisabledException 

class CustomUserDetailsContextMapper implements UserDetailsContextMapper { 

    private static final List NO_ROLES = [new GrantedAuthorityImpl(SpringSecurityUtils.NO_ROLE)] 

    def dataSource 

    @Override 
    public CustomUserDetails mapUserFromContext(DirContextOperations ctx, String username, Collection<GrantedAuthority> authority) { 

     username = username.toLowerCase() 

     User user = User.findByUsername(username) 

     String firstName = ctx.originalAttrs.attrs['givenname'].values[0] 
     String lastName = ctx.originalAttrs.attrs['sn'].values[0] 


     def roles 

     User.withTransaction { 

      if(!user){ 
       user = new User(username: username, enabled: true, firstName: firstName, lastName: lastName) 
       user.save(flush: true) 
      } 
      else { 
       user = User.findByUsername(username) 
       user.firstName = firstName 
       user.lastName = lastName 
       user.save(flush: true) 
      } 

      roles = user.getAuthorities() 
     } 

     if (!user.enabled) 
      throw new DisabledException("User is disabled", username) 


     def authorities = roles.collect { new GrantedAuthorityImpl(it.authority) } 
     authorities.addAll(authority) 
     def userDetails = new CustomUserDetails(username, user.password, user.enabled, false, false, false, authorities, user.id, user.firstName, user.lastName) 

     return userDetails 
    } 

    @Override 
    public void mapUserToContext(UserDetails arg0, DirContextAdapter arg1) { 
    } 
} 

봄/리소스 구성 중입니다.그루비 : Config.groovy 파일에서

import yourpackagenamehere.CustomUserDetailsService 
import yourpackagenamehere.CustomUserDetailsContextMapper 
beans = { 
    userDetailsService(CustomUserDetailsService) 

    ldapUserDetailsMapper(CustomUserDetailsContextMapper) { 
     dataSource = ref("dataSource") 
    } 
} 

, 여기 내 설정은 다음과 같습니다

다음
grails.plugins.springsecurity.ldap.context.managerDn = 'CN=username,OU=People,DC=foo,DC=com' 
grails.plugins.springsecurity.ldap.context.managerPassword = 'password' 
grails.plugins.springsecurity.ldap.context.server = 'ldap://foo.com:389/' 
grails.plugins.springsecurity.ldap.authorities.ignorePartialResultException = true 
grails.plugins.springsecurity.ldap.search.base = 'ou=People,dc=foo,dc=com' 
grails.plugins.springsecurity.ldap.search.filter="sAMAccountName={0}" 
grails.plugins.springsecurity.ldap.search.searchSubtree = true 
grails.plugins.springsecurity.ldap.auth.hideUserNotFoundExceptions = false 
grails.plugins.springsecurity.ldap.search.attributesToReturn = null 
grails.plugins.springsecurity.providerNames = ['ldapAuthProvider', 'anonymousAuthenticationProvider'] 
grails.plugins.springsecurity.ldap.mapper.userDetailsClass = 'CustomUserDetails' 

grails.plugins.springsecurity.ldap.authorities.retrieveGroupRoles = true 
grails.plugins.springsecurity.ldap.authorities.retrieveDatabaseRoles = true 
grails.plugins.springsecurity.ldap.authorities.groupSearchBase ='dc=foo,dc=com' 
grails.plugins.springsecurity.ldap.authorities.groupSearchFilter = 'member={0}' 
+0

귀하의 제안에 따라 작동되도록 노력하겠습니다. – Viriato

+0

정말 고마워요 !!! 문서를 읽은 후에 http://grails-plugins.github.io/grails-spring-security-ldap/docs/manual/guide/2.%20Usage.html 그 두 클래스를 오버라이드하는 것이 장난. 또한 도메인 클래스에서 true와 공백을 true로 설정할 수있을뿐만 아니라 데이터베이스 측에서 nullable 'Y'인지 확인해야합니다. 나는 DirContextOperations 객체가 항상 null이되는 문제를 앱을 실행할 때 가지고있다. 그것이 무엇인지는 모르지만, 나는 지금 그것으로 살 수 있습니다. – Viriato

+0

너도 알다시피, 전에 그 실수를 했어! AIX에서 실행될 때 실패했지만 Windows에서는 작동합니다. 2 대의 기계는 다른 서브넷에 있고 나는 네트워크 문제까지 그것을 요약했다. 네가 알아 내면 알려줘 !!!!!!!! –