【问题标题】:Spring JAAS Authentication with database authorization具有数据库授权的 Spring JAAS 身份验证
【发布时间】:2015-10-12 18:07:24
【问题描述】:

我正在使用 Spring 安全 4.0。我的登录模块是在应用程序服务器中配置的,所以我必须使用 JAAS 进行身份验证,但我的用户详细信息存储在数据库中,因此一旦通过身份验证的用户对象将通过查询数据库创建。您能否让我知道如何实现这一点,即 LDAP 身份验证并从数据库加载用户详细信息。还有如何使用eh-cache缓存用户对象,以便在service/dao层访问用户对象。

【问题讨论】:

    标签: spring caching spring-security jaas spring-security-ldap


    【解决方案1】:

    这可以使用 CustomAuthentication Provider 来实现。以下是代码。

    import java.util.Arrays;
    import java.util.List;
    
    import org.springframework.security.authentication.AuthenticationProvider;
    import org.springframework.security.authentication.BadCredentialsException;
    import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
    import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
    import org.springframework.security.authentication.jaas.JaasGrantedAuthority;
    import org.springframework.security.core.Authentication;
    import org.springframework.security.core.AuthenticationException;
    import org.springframework.security.core.GrantedAuthority;
    import org.springframework.security.core.userdetails.UserDetails;
    
    import com.sun.security.auth.UserPrincipal;
    
    public class CustomAutenticationProvider extends DaoAuthenticationProvider implements AuthenticationProvider {
        private AuthenticationProvider delegate;
    
        public CustomAutenticationProvider(AuthenticationProvider delegate) {
            this.delegate = delegate;
        }
    
        @Override
        public Authentication authenticate(Authentication authentication) {
            Authentication a = delegate.authenticate(authentication);
    
            if(a.isAuthenticated()){
                a = super.authenticate(a);
            }else{
                throw new BadCredentialsException(messages.getMessage(
                        "AbstractUserDetailsAuthenticationProvider.badCredentials",
                        "Bad credentials"));
            }
    
            return a;
        }
    
        private List<GrantedAuthority> loadRolesFromDatabaseHere(String name) {
            GrantedAuthority grantedAuthority =new JaasGrantedAuthority(name, new UserPrincipal(name));
            return Arrays.asList(grantedAuthority);
        }
    
        @Override
        public boolean supports(Class<?> authentication) {
            return delegate.supports(authentication);
        }
    
        /* (non-Javadoc)
         * @see org.springframework.security.authentication.dao.DaoAuthenticationProvider#additionalAuthenticationChecks(org.springframework.security.core.userdetails.UserDetails, org.springframework.security.authentication.UsernamePasswordAuthenticationToken)
         */
        @Override
        protected void additionalAuthenticationChecks(UserDetails userDetails,
                UsernamePasswordAuthenticationToken authentication)
                        throws AuthenticationException {
    
    
            if(!authentication.isAuthenticated())
                throw new BadCredentialsException(messages.getMessage(
                        "AbstractUserDetailsAuthenticationProvider.badCredentials",
                        "Bad credentials"));
    
    
        }
    }
    

    DAOAuthentication 所需的用户详细信息

    import org.springframework.security.core.userdetails.UserDetails;
    import org.springframework.security.core.userdetails.UserDetailsService;
    import org.springframework.security.core.userdetails.UsernameNotFoundException;
    import org.springframework.stereotype.Component;
    
    import com.testjaas.model.User;
    import com.testjaas.model.UserRepositoryUserDetails;
    
    
    @Component
    public class AuthUserDetailsService implements UserDetailsService {
    
    
        @Override
        public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
            System.out.println("loadUserByUsername called !!");
            com.testjaas.model.User user = new User();
            user.setName(username);
            user.setUserRole("ROLE_ADMINISTRATOR");
            if(null == user) {
                throw new UsernameNotFoundException("User " + username + " not found.");
            }
    
            return new UserRepositoryUserDetails(user);
        }
    
    
    }
    

    RoleGrantor - 这将是 Spring JAAS 身份验证所需的虚拟类

    import java.security.Principal;
    import java.util.Collections;
    import java.util.HashMap;
    import java.util.Map;
    import java.util.Set;
    
    import org.springframework.security.authentication.jaas.AuthorityGranter;
    
    public class RoleGranterFromMap implements AuthorityGranter {
    
        private static Map<String, String> USER_ROLES = new HashMap<String, String>();
    
        static {
            USER_ROLES.put("test", "ROLE_ADMINISTRATOR");
            //USER_ROLES.put("test", "TRUE");
        }
    
        public Set<String> grant(Principal principal) {
            return Collections.singleton("DUMMY");
        }
    }
    

    SampleLogin - 这应该替换为您的登录模块

    import java.io.Serializable;
    import java.security.Principal;
    import java.util.HashMap;
    import java.util.Map;
    
    import javax.security.auth.Subject;
    import javax.security.auth.callback.Callback;
    import javax.security.auth.callback.CallbackHandler;
    import javax.security.auth.callback.NameCallback;
    import javax.security.auth.callback.PasswordCallback;
    import javax.security.auth.login.LoginException;
    import javax.security.auth.spi.LoginModule;
    
    public class SampleLoginModule implements LoginModule {
    
        private Subject subject;
        private String password;
        private String username;
        private static Map<String, String> USER_PASSWORDS = new HashMap<String, String>();
    
        static {
            USER_PASSWORDS.put("test", "test");
        }
    
        public boolean abort() throws LoginException {
            return true;
        }
    
        public boolean commit() throws LoginException {
            return true;
        }
    
        public void initialize(Subject subject, CallbackHandler callbackHandler,
                Map<String, ?> sharedState, Map<String, ?> options) {
            this.subject = subject;
    
            try {
                NameCallback nameCallback = new NameCallback("prompt");
                PasswordCallback passwordCallback = new PasswordCallback("prompt",false);
    
                callbackHandler.handle(new Callback[] { nameCallback,passwordCallback });
    
                this.password = new String(passwordCallback.getPassword());
                this.username = nameCallback.getName();
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }
    
        public boolean login() throws LoginException {
    
            if (USER_PASSWORDS.get(username) == null
                    || !USER_PASSWORDS.get(username).equals(password)) {
                throw new LoginException("username is not equal to password");
            }
    
            subject.getPrincipals().add(new CustomPrincipal(username));
            return true;
        }
    
        public boolean logout() throws LoginException {
            return true;
        }
    
        private static class CustomPrincipal implements Principal, Serializable {
            private final String username;
    
            public CustomPrincipal(String username) {
                this.username = username;
            }
    
            public String getName() {
                return username;
            }
        }
    
    }
    

    Spring XML 配置

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:security="http://www.springframework.org/schema/security"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:jdbc="http://www.springframework.org/schema/jdbc"
        xsi:schemaLocation="http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.1.xsd
            http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-4.0.xsd
            http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.1.xsd">
        <security:http auto-config="true">
            <security:intercept-url pattern="/*" access="isAuthenticated()"/>
        </security:http>
        <!-- <security:authentication-manager>
            <security:authentication-provider ref="jaasAuthProvider" />
        </security:authentication-manager> -->
    
        <bean id="userDetailsService" class="com.testjaas.service.AuthUserDetailsService"></bean>
        <bean id="testService" class="com.testjaas.service.TestService"/>
        <bean id="applicationContextProvider" class="com.testjaas.util.ApplicationContextProvider"></bean>
    
        <security:authentication-manager>
            <security:authentication-provider ref="customauthProvider"/>
        </security:authentication-manager>
    
        <bean id="customauthProvider" class="com.testjaas.security.CustomAutenticationProvider">
            <constructor-arg name="delegate" ref="jaasAuthProvider" />
            <property name="userDetailsService" ref="userDetailsService" />
        </bean>
    
        <bean id="jaasAuthProvider" class="org.springframework.security.authentication.jaas.JaasAuthenticationProvider">
            <property name="loginConfig" value="classpath:pss_jaas.config" />
            <property name="authorityGranters">
                <list>
                    <bean class="com.testjaas.security.RoleGranterFromMap" />
                </list>
            </property>
            <property name="loginContextName" value="JASSAuth" />
            <property name="callbackHandlers">
                <list>
                    <bean class="org.springframework.security.authentication.jaas.JaasNameCallbackHandler" />
                    <bean class="org.springframework.security.authentication.jaas.JaasPasswordCallbackHandler" />
                </list>
            </property>
        </bean>
    </beans>
    

    示例 jaas 配置

    JASSAuth {
      com.testjaas.security.SampleLoginModule required;
    };
    

    【讨论】:

      猜你喜欢
      • 2014-05-11
      • 2012-09-25
      • 2021-02-24
      • 2012-03-02
      • 2012-04-24
      • 1970-01-01
      • 2019-10-04
      • 2012-10-25
      • 2011-11-19
      相关资源
      最近更新 更多