SpringSecurityの追加フィルタ

26017 ワード

ケース:検証コード検証の実装
1.フィルタによる検証コード検証
1.1フィルタの作成
/**
*spring security          ,    filter  。
*   spring       OncePerRequestFilter(                )
*/
public class VerificationCodeFilter extends OncePerRequestFilter {
	//            
    private AuthenticationFailureHandler handler = new MyAuthenticationFailureHandler();

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
    	//    url        ,    
        if(!"/auth/login".equals(request.getRequestURI())){
            filterChain.doFilter(request,response);
        }else{
            try{
            	//  session       request    ,         
                verifyCode(request);
                filterChain.doFilter(request,response);
            }catch (Exception e){
                handler.onAuthenticationFailure(request,response,e);
            }

        }
    }
}

2.spring securityのフィルタチェーンにフィルタを追加する
public void configure(HttpSecurity http) throws Exception{
	//           UsernamePasswordAuthenticationFilter  
	http.addFilterBefore(new VerificationCodeFilter(),UsernamePasswordAuthenticationFilter.class);
}

2.カスタム実装検証コード検証
2.1 AuthenticationProviderの説明
Spring Securityでは、システム内のユーザーを本体と呼び、1層のパッケージでAuthenticationと定義します.
public interface Authentication extends Principal, Serializable {
	//          
    Collection<? extends GrantedAuthority> getAuthorities();
	//       ,         
    Object getCredentials();
	//            
    Object getDetails();
	//     ,       
    Object getPrincipal();
	//          
    boolean isAuthenticated();

    void setAuthenticated(boolean var1) throws IllegalArgumentException;
}

AuthenticationProviderの場合、Spring Securityによって検証プロセスとして定義されます.
public interface AuthenticationProvider {
	//     ,           Authentication 
    Authentication authenticate(Authentication var1) throws AuthenticationException;
	//          Authentication  
    boolean supports(Class<?> var1);
}


1回の検証プロセスには、providerManagerによって統合管理される複数のAuthenticationProviderが含まれる場合があります.
2.2 AuthenticationProviderのカスタマイズ
  • まずspring securityは抽象的なproviderを提供した:A b s t r a c t U s e r D e tailsAuthenticationProvider
  • A b s t r a c t U s e r D e tailsAuthenticationProviderでは、基本的な認証プロセス
  • が提供されています.
  • したがって、このクラスを統合し、retrieveUserとadditionalAuthenticationChecksの2つの抽象的な方法を実装することで、コア認証プロセス
  • をカスタマイズすることができます.
  • spring securityは、A b s t r a c t U s e r D e tailsAuthenticationProviderから引き継いだDaoAuthenticationProvider
  • も提供しています.
    2.3グラフィック検証コードを実現するAuthenticationProvider
    public class MyAuthenticationProvider extends DaoAuthenticationProvider {
    
    
        public MyAuthenticationProvider(UserDetailsService userDetailsService, PasswordEncoder encoder){
            this.setUserDetailsService(userDetailsService);
            this.setPasswordEncoder(encoder);
        }
    
    
        @Override
        protected void additionalAuthenticationChecks(UserDetails userDetails, UsernamePasswordAuthenticationToken authentication) throws AuthenticationException {
           //          
    	
    	   //              
    	   super.additionalAuthenticationChecks(userDetails, authentication);
        }
    }
    

    認証コードは一般にセッションに存在し、ユーザが入力した認証コードはrequestに存在するが、上記のadditionalAuthenticationChecksメソッドにはrequestパラメータがないため、追加する必要がある
    U s e r a m e P a s s s s w o r d AuthenticationFilterで使用されているAuthenticationDetailsSourceは、ユーザーのsesionIdとIPアドレスを携帯する標準的なWeb認証ソースです.
    public class WebAuthenticationDetailsSource implements AuthenticationDetailsSource<HttpServletRequest, WebAuthenticationDetails> {
        public WebAuthenticationDetailsSource() {
        }
    
        public WebAuthenticationDetails buildDetails(HttpServletRequest context) {
            return new WebAuthenticationDetails(context);
        }
    }
    
    public class WebAuthenticationDetails implements Serializable {
        private static final long serialVersionUID = 520L;
        private final String remoteAddress;
        private final String sessionId;
    
        public WebAuthenticationDetails(HttpServletRequest request) {
            this.remoteAddress = request.getRemoteAddr();
            HttpSession session = request.getSession(false);
            this.sessionId = session != null ? session.getId() : null;
        }
    
        private WebAuthenticationDetails(String remoteAddress, String sessionId) {
            this.remoteAddress = remoteAddress;
            this.sessionId = sessionId;
        }
        ...
    

    WebAuthenticationDetailsを継承し、必要な情報を拡張することができます.
    public class MyWebAuthenticationDetails extends WebAuthenticationDetails {
        
        //             
        private Boolean imageCodeIsRight;
        
        // setter and getter
        
        public MyWebAuthenticationDetails(HttpServletRequest request) {
        
        
            String imageCode = request.getParameter("imageCode");
            String generatedImageCode = (String) request.getSession().getAttribute("generatedImageCode");
        
            /*                imageCodeIsRight    */
            if(  ){
    			this.imageCodeIsRight = true
    		}else{
    			this.imageCodeIsRight = false
    		}
            super(request);
        }
    }
    
    
    @Component
    public class MyWebAuthenticationDetailsSource implements WebAuthenticationDetailsSource<HttpServletRequest, WebAuthenticationDetails> {
        
        @Override
        public WebAuthenticationDetails buildDetails(HttpServletRequest request){
            
            return new MyWebAuthenticationDetails(request);
        }
    
    }
    

    上で定義してspringコンテナにMyW e b u t h e n t i c a tionDetailsSourceを入れると、S e r n a m e P a s s s s s w o r d AuthenticationTokenでMyW e b u t h e nticationDetailsを取得できます.
    
    	public class MyAuthenticationProvider extends DaoAuthenticationProvider {
    
    
        public MyAuthenticationProvider(UserDetailsService userDetailsService, PasswordEncoder encoder){
            this.setUserDetailsService(userDetailsService);
            this.setPasswordEncoder(encoder);
        }
    
    
        @Override
        protected void additionalAuthenticationChecks(UserDetails userDetails, UsernamePasswordAuthenticationToken authentication) throws AuthenticationException {
           //          
    		MyWebAuthenticationDetails details = (MyWebAuthenticationDetails )UsernamePasswordAuthenticationToken.getDetails();
    		if(!details.getImageCodeIsRight()){
    			//         ,    
    		}
    	   //              
    	   super.additionalAuthenticationChecks(userDetails, authentication);
        }
    }
    
    

    WebSecurityConfigでAuthenticationProviderとAuthenticationDetailsSourceを構成します.
    
    1.  WebSecurityConfig   @autowire      MyWebAuthenticationDetailsSource(    @component      spring )
    a
    2. WebSecurityConfig   @autowire      AuthenticationProvider
    2. protected void configure(AuthenticationManagerBuilder auth) throws Exception{
    		auth.authenticationProvider(authenticationProvider);
       }
    
    3.protected void configure(HttpSecurity http) throws Exception{
    		http....
    			.formLogin()
    			.authenticationDetailsSource(myWebAuthenticationDetailsSource)
    
      }