質問

I am developing a web application with spring mvc framework and java. I am using active directory user authentication in the application.

Now i want to assign role to these users from a sql database. So the whole authentication process will be done by taking information from two sources: [ user id & password from active directory & roles of user from sql database ].

I have searched on internet to get any tutorial/samples to do so but I'm unable to get any useful stuff. So any help on the issue will be appreciated.

Here is the current code of my spring security file,

<bean id="adAuthenticationProvider"
      class="org.springframework.security.ldap.authentication.ad.ActiveDirectoryLdapAuthenticationProvider">
    <constructor-arg value="abbl.org"/>
    <constructor-arg value="LDAP://abbl.org"/>
    <property name="convertSubErrorCodesToExceptions" value="true"/>
    <property name="useAuthenticationRequestCredentials" value="true"/>
</bean>

<bean id="customAuthenticationProvider"
      class="org.abbl.exhbp.templates.CustomAuthorityProvider">
    <constructor-arg ref="adAuthenticationProvider"/>
</bean>

<security:authentication-manager>
    <security:authentication-provider ref="customAuthenticationProvider"/>
</security:authentication-manager>

my authenticate function in AuthenticationProvider class,

public Authentication authenticate(Authentication authentication) {

    final Authentication a = delegate.authenticate(authentication);

    // Load additional authorities and create an Authentication object
    final List<GrantedAuthority> authorities = getGrantedAuthorities(a.getName());

    return new AbstractAuthenticationToken(authorities) {
        @Override
        public Object getCredentials() {
            //return null;  //To change body of implemented methods use File | Settings | File Templates.
            throw new UnsupportedOperationException();
        }

        @Override
        public Object getPrincipal() {
            //return null; //To change body of implemented methods use File | Settings | File Templates.
            return a.getPrincipal();
        }
    };
}

After login , i am getting this exception,

java.lang.UnsupportedOperationException
org.abbl.exhbp.templates.CustomAuthorityProvider$1.getCredentials(CustomAuthorityProvider.java:41)
org.springframework.security.authentication.AbstractAuthenticationToken.eraseCredentials(AbstractAuthenticationToken.java:108)
org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:186)
org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:174)
org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter.attemptAuthentication(UsernamePasswordAuthenticationFilter.java:94)
org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:195)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:105)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:87)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:192)
org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:160)
org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:346)
org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:259)

What modification or implementation I need to do here to achieve what i mentioned above?

役に立ちましたか?

解決

Finally i achieved what i aimed for by using UsernamePasswordAuthenticationToken instead of AbstractAuthenticationToken. Solution is given below,

1) spring-security.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xmlns:security="http://www.springframework.org/schema/security"
   xsi:schemaLocation="http://www.springframework.org/schema/beans
   http://www.springframework.org/schema/beans/spring-beans.xsd
   http://www.springframework.org/schema/security
   http://www.springframework.org/schema/security/spring-security.xsd">


<security:http auto-config="true" use-expressions="true">
    <security:anonymous enabled="false"/>
    <security:form-login login-page="/login" default-target-url="/home"
                         login-processing-url="/j_spring_security_check"
                         authentication-failure-url="/loginfailed"/>
    <security:logout logout-success-url="/logout"/>
</security:http>

<bean id="adAuthenticationProvider"
      class="org.springframework.security.ldap.authentication.ad.ActiveDirectoryLdapAuthenticationProvider">
    <constructor-arg value="DOMAIN"/>
    <constructor-arg value="URL"/>
    <property name="convertSubErrorCodesToExceptions" value="true"/>
    <property name="useAuthenticationRequestCredentials" value="true"/>
</bean>

<bean id="customAuthenticationProvider"
      class="org.abbl.exhbp.templates.CustomAuthorityProvider">
    <constructor-arg ref="adAuthenticationProvider"/>
</bean>

<security:authentication-manager>
    <security:authentication-provider ref="customAuthenticationProvider"/>
</security:authentication-manager>

2) CustomAuthorityProvider.class

public class CustomAuthorityProvider implements AuthenticationProvider {

private AuthenticationProvider delegate;

public CustomAuthorityProvider(AuthenticationProvider delegate) {
    this.delegate = delegate;
}

public Authentication authenticate(Authentication authentication) {

    final Authentication a = delegate.authenticate(authentication);

    // Load additional authorities and create an Authentication object
    final List<GrantedAuthority> authorities = getGrantedAuthorities(a.getName());

    return new UsernamePasswordAuthenticationToken(a.getPrincipal(),a.getCredentials(),authorities);
}

@Override
public boolean supports(Class<?> authentication) {
    return delegate.supports(authentication);
}

List<GrantedAuthority> getGrantedAuthorities(String username) {
    JdbcTemplateDataSource ds = new JdbcTemplateDataSource();
    List<GrantedAuthority> roles = ds.getJdbcTemplate().query("select r.Role from Users u join UserRole ur on u.UserId = "
            + "ur.UserId join Roles r on r.RoleId = ur.RoleId where Username = ?",
            new String[]{username},
            new RowMapper<GrantedAuthority>() {
                public GrantedAuthority mapRow(ResultSet rs, int rowNum) throws SQLException {
                    return new SimpleGrantedAuthority(rs.getString(1));
                }
            });
    return roles;
}
}
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top