spring security 4カスタムログイン認証コードの設定

18842 ワード

最近やったプロジェクトの中でspring securityを使って権限を管理しています.これまで接触したことがないので、インターネットで長い間資料を探して研究しました.記録したいです.securityのバージョンは4.2を使っています.ネット上の多くの文章はすでに3.xと4.xの違いを説明していると信じています.ここでは説明しません.以下に準備作業を説明します.
関連jarパッケージ、pomダウンロード:
<dependency>
    <groupId>org.springframework.securitygroupId>
    <artifactId>spring-security-ldapartifactId>
    <version>4.2.2.RELEASEversion>
dependency>

<dependency>
    <groupId>org.springframework.securitygroupId>
    <artifactId>spring-security-coreartifactId>
    <version>4.2.2.RELEASEversion>
dependency>

<dependency>
    <groupId>org.springframework.securitygroupId>
    <artifactId>spring-security-webartifactId>
    <version>4.2.2.RELEASEversion>
dependency>
本プロジェクトで使用しているユーザーは会社のldapから取得しているので、spring-security-ldapパッケージも入れています.
設定:
次はsecurityの配置です.構成については、「名前空間」の方式と「java config」の方式に分けることができます.
ここで使用するのは名前空間の構成方法です.

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:s="http://www.springframework.org/schema/security" 
    xmlns:beans="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/security
                        http://www.springframework.org/schema/security/spring-security-4.2.xsd
                        http://www.springframework.org/schema/beans
                        http://www.springframework.org/schema/beans/spring-beans-4.2.xsd">


    
    
    <s:http pattern="/images/**" security="none" />
    <s:http pattern="/js/**" security="none" />
    <s:http pattern="/css/**" security="none" />
    
    <s:http use-expressions="true" auto-config='true'>
        
        <s:intercept-url pattern="/loginPage" access="hasRole('ROLE_ANONYMOUS')" />
        <s:intercept-url pattern="/**"
            access="hasAnyRole('ROLE_OPER','ROLE_ADMIN')" />
            
        <s:form-login login-page="/loginPage" 
                        username-parameter="username"
                        password-parameter="password" 
                        default-target-url='/homepage/index'
                        always-use-default-target='true' />
        <s:csrf disabled="false" />
        <s:logout logout-url="/logout" logout-success-url="/login" />
        
        <s:custom-filter before="FORM_LOGIN_FILTER" ref="myFilter" /> 
    s:http>

    
    <beans:bean id="myFilter" class="com.onstar.bdif.common.filters.MySpecialAuthenticationFilter">
        <property name="authenticationManager" ref="authenticationManager" />
        
        <property name="authenticationSuccessHandler" ref="successHandler" />
        
        <property name="authenticationFailureHandler" ref="simpleUrlAuthenticationFailureHandler" />
    beans:bean>
    
    <bean id="successHandler" class="org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler">
        <property name="defaultTargetUrl" value="/homepage/index" />
    bean>
    
    <bean id="simpleUrlAuthenticationFailureHandler"
     class="org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler">
        <property name="defaultFailureUrl" value="/loginPage" />
    bean>

    
    
    <s:authentication-manager id="authenticationManager" erase-credentials="false">
        
        <s:ldap-authentication-provider
            user-details-class="inetOrgPerson" group-search-filter="uniqueMember={0}"
            role-prefix="xx" group-search-base="ou=xx"
            user-dn-pattern="uid={0},ou=user,ou=xx" server-ref="ldapContextSource" />
    s:authentication-manager>
    
    <s:ldap-server id="ldapContextSource"
        url="ldap://xx.xx.xx.xx:xx/ou=xx,ou=xx,o=xx.com" />
beans>
プロジェクトには認証コードの機能が使用されており、フロントエンドのログインページにはパスワード暗号化の一つの方法が追加されていますので、上述のようにユーザー定義のfilterを挿入して検証コードを検証し、暗号化されていないパスワードを復元して、ldapの検証に役立てます.
//   UsernamePasswordAuthenticationFilter
public class MySpecialAuthenticationFilter extends UsernamePasswordAuthenticationFilter {


    private Logger logger = LogManager.getLogger(MySpecialAuthenticationFilter.class);

    public static final String SPRING_SECURITY_FORM_USERNAME_KEY = "bdifacun";
    public static final String SPRING_SECURITY_FORM_BDIFACPWD_KEY = "bdifacpwd";
    private String usernameParameter = SPRING_SECURITY_FORM_USERNAME_KEY;
    private String bdifacpwdParameter = SPRING_SECURITY_FORM_BDIFACPWD_KEY;
    private boolean postOnly = true;

    //         
    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response)
            throws AuthenticationException {
        if (postOnly && !request.getMethod().equals("POST")) {
            throw new AuthenticationServiceException(
                    "Authentication method not supported: " + request.getMethod());
        }

        HttpSession session = request.getSession();
        String username = obtainUsername(request);
        String bdifacpwd = obtainPassword(request);
        //    
        String inputValidateCode = request.getParameter("inputValidateCode");
        //              
        if (StringUtils.isEmpty(username) || StringUtils.isEmpty(bdifacpwd)) {
            session.setAttribute("errorMsg", "          !");
            throw new AuthenticationServiceException("username or bdifacpwd is not null!"); 
        }else {
            bdifacpwd = AesUtil.aesDecrypt(bdifacpwd, OnstarConstans.AES_LOGIN_KEY);
        }
        //  session      ,            
        String sessionCaptcha = (String) session.getAttribute("validateCode");
        if (StringUtils.isEmpty(inputValidateCode) || StringUtils.isEmpty(sessionCaptcha)) {
            session.setAttribute("errorMsg", "     !");
            throw new AuthenticationServiceException("the session validate is not null!");
        }
        //   Sesion     
        session.removeAttribute("validateCode");
        //        
        if (!sessionCaptcha.equalsIgnoreCase(inputValidateCode)) {
            session.setAttribute("errorMsg", "       !");
            throw new AuthenticationServiceException("the validate is error!");
        }
        UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(username, bdifacpwd);
        setDetails(request, authRequest);
        Authentication authen = null;
        //   ldap     
        try {
            authen = this.getAuthenticationManager().authenticate(authRequest);
        } catch (AuthenticationException failed) {
            session.setAttribute("errorMsg", "        !");
            throw new AuthenticationServiceException("the validate is error!");
        }
        session.setAttribute("managerSession", username);
        return authen;
    }

    protected String obtainPassword(HttpServletRequest request) {
        return request.getParameter(bdifacpwdParameter);
    }

    protected String obtainUsername(HttpServletRequest request) {
        return request.getParameter(usernameParameter);
    }

    protected void setDetails(HttpServletRequest request, UsernamePasswordAuthenticationToken authRequest) {
        authRequest.setDetails(authenticationDetailsSource.buildDetails(request));
    }
}
以上でsecurity登録の検証コードとフロントエンドのカスタムパスワード暗号化の検証ができます.文章は簡潔ではありません.後で確認するためにメモしてください.