Spring Security 自定义登录验证与自定义回调地址

1 配置文件 security-ns.xml
   
     
    

    //需要过滤不被拦截的请求
    
    
    
   
     //entry-point-ref 配置自定义登录
    
        
        
        
        
        
        
        
        
        
        
    
        //需要替换的Filter顺序,配置自定义custom-filter时必须蔣auto-config="false",不然会报已经存在同样的过滤器错误
        
        //登出配置
        
    

     //密码加密工具类
    
    //认证管理器
    
        //UserDetailsService实现 主要用于用户的查询
        
            
            
        
    

    
        
        
        
    

    //成功登录后
    
        
    
    //登录失败
    
        
    
    
    
        
    



2 UserLoginServiceImpl 查询用户实现类

     @Named("userLoginService")
public class UserLoginServiceImpl  implements UserDetailsService ,LoginService{

    @Inject
    private UserLoginDAO userLoginDAO;
    
    @Override
    public WrappedUserLogin getUserLogin() {
        try {
            WrappedUserLogin wrappedUserLogin = (WrappedUserLogin) SecurityContextHolder
                    .getContext().getAuthentication().getPrincipal();
            return wrappedUserLogin;
        } catch (Exception e) {
            return null;
        }
    }

    @Override
    public UserDetails loadUserByUsername(String username)
            throws UsernameNotFoundException {
        System.out.println("用户名-------------"+username);
        UserLogin userLogin =  null;
        if(username != null && !"".equals(username)&& username.indexOf("@") > 0){
              userLogin = userLoginDAO.findByEmail(username);
              username = userLogin.getNick();
        }else{
            userLogin = userLoginDAO.findByNick(username);
        }
        System.out.println("user is null ---"+userLogin.getUserType());
        String nick = userLogin.getNick();
        String email = userLogin.getEmail();
        String mobile = userLogin.getMobile();
        int userType = userLogin.getUserType();
        List resultAuths = new ArrayList();
        

        // 前台用户
        if (userType == 1) {
            resultAuths.add(new SimpleGrantedAuthority("ROLE_USER"));
        } else {
            resultAuths.add(new SimpleGrantedAuthority("ROLE_BACK_USER"));
        }
        
        return new WrappedUserLogin(userLogin.getId(), email, nick, mobile, userLogin.getPassword(), userType,resultAuths);
    }

}

3 重写用户名密码验证
     public class MyUsernamePasswordAuthenticationFilter extends UsernamePasswordAuthenticationFilter{
        //用户名
        public static final String SPRING_SECURITY_FORM_USERNAME_KEY = "j_username";
        //密码
        public static final String SPRING_SECURITY_FORM_PASSWORD_KEY = "j_password";
        //需要回调的URL 自定义参数
        public static final String SPRING_SECURITY_FORM_REDERICT_KEY = "spring-security-redirect";
        
        /**
         * @deprecated If you want to retain the username, cache it in a customized {@code AuthenticationFailureHandler}
         */
        @Deprecated
        public static final String SPRING_SECURITY_LAST_USERNAME_KEY = "SPRING_SECURITY_LAST_USERNAME";

        private String usernameParameter = SPRING_SECURITY_FORM_USERNAME_KEY;
        private String passwordParameter = SPRING_SECURITY_FORM_PASSWORD_KEY;
        private String redirectParameter = SPRING_SECURITY_FORM_REDERICT_KEY;
        private boolean postOnly = true;

        //~ Constructors ===================================================================================================

        public MyUsernamePasswordAuthenticationFilter() {
           super();
        }

        //~ Methods ========================================================================================================

        public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
            if (postOnly && !request.getMethod().equals("POST")) {
                throw new AuthenticationServiceException("Authentication method not supported: " + request.getMethod());
            }
            String username = obtainUsername(request);
            String password = obtainPassword(request);
            String redirectUrl = obtainRedercitUrl(request);
            if (username == null) {
                username = "";
            }

            if (password == null) {
                password = "";
            }
            //自定义回调URL,若存在则放入Session
            if(redirectUrl != null && !"".equals(redirectUrl)){
                request.getSession().setAttribute("callCustomRediretUrl", redirectUrl);
            }
            username = username.trim();
            UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(username, password);
            // Allow subclasses to set the "details" property
            setDetails(request, authRequest);
            return this.getAuthenticationManager().authenticate(authRequest);
        }

        /**
         * Enables subclasses to override the composition of the password, such as by including additional values
         * and a separator.

This might be used for example if a postcode/zipcode was required in addition to the * password. A delimiter such as a pipe (|) should be used to separate the password and extended value(s). The * AuthenticationDao will need to generate the expected password in a corresponding manner.

* * @param request so that request attributes can be retrieved * * @return the password that will be presented in the Authentication request token to the * AuthenticationManager */ protected String obtainPassword(HttpServletRequest request) { return request.getParameter(passwordParameter); } /** * Enables subclasses to override the composition of the username, such as by including additional values * and a separator. * * @param request so that request attributes can be retrieved * * @return the username that will be presented in the Authentication request token to the * AuthenticationManager */ protected String obtainUsername(HttpServletRequest request) { return request.getParameter(usernameParameter); } protected String obtainRedercitUrl(HttpServletRequest request) { return request.getParameter(redirectParameter); } /** * Provided so that subclasses may configure what is put into the authentication request's details * property. * * @param request that an authentication request is being created for * @param authRequest the authentication request object that should have its details set */ protected void setDetails(HttpServletRequest request, UsernamePasswordAuthenticationToken authRequest) { authRequest.setDetails(authenticationDetailsSource.buildDetails(request)); } /** * Sets the parameter name which will be used to obtain the username from the login request. * * @param usernameParameter the parameter name. Defaults to "j_username". */ public void setUsernameParameter(String usernameParameter) { Assert.hasText(usernameParameter, "Username parameter must not be empty or null"); this.usernameParameter = usernameParameter; } /** * Sets the parameter name which will be used to obtain the password from the login request.. * * @param passwordParameter the parameter name. Defaults to "j_password". */ public void setPasswordParameter(String passwordParameter) { Assert.hasText(passwordParameter, "Password parameter must not be empty or null"); this.passwordParameter = passwordParameter; } /** * Defines whether only HTTP POST requests will be allowed by this filter. * If set to true, and an authentication request is received which is not a POST request, an exception will * be raised immediately and authentication will not be attempted. The unsuccessfulAuthentication() method * will be called as if handling a failed authentication. *

* Defaults to true but may be overridden by subclasses. */ public void setPostOnly(boolean postOnly) { this.postOnly = postOnly; } } 4 SimpleUrlAuthenticationSuccessHandler重写 public class MySavedRequestAwareAuthenticationSuccessHandler extends SimpleUrlAuthenticationSuccessHandler{ @Value(value = "${local.service.url}") private String LOCAL_SERVER_URL; protected final Log logger = LogFactory.getLog(this.getClass()); private RequestCache requestCache = new HttpSessionRequestCache(); @Override public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws ServletException, IOException { SavedRequest savedRequest = requestCache.getRequest(request, response); if (savedRequest == null) { System.out.println("savedRequest is null "); //用户判断是否要使用上次通过session里缓存的回调URL地址 int flag = 0; //通过提交登录请求传递需要回调的URL callCustomRediretUrl if(request.getSession().getAttribute("callCustomRediretUrl") != null && !"".equals(request.getSession().getAttribute("callCustomRediretUrl"))){ String url = String.valueOf(request.getSession().getAttribute("callCustomRediretUrl")); //若session 存在则需要使用自定义回调的URL 而不是缓存的URL super.setDefaultTargetUrl(url); super.setAlwaysUseDefaultTargetUrl(true); flag = 1; request.getSession().setAttribute("callCustomRediretUrl", ""); } //重设置默认URL为主页地址 if(flag == 0){ super.setDefaultTargetUrl(LOCAL_SERVER_URL); } super.onAuthenticationSuccess(request, response, authentication); return; } //targetUrlParameter 是否存在 String targetUrlParameter = getTargetUrlParameter(); if (isAlwaysUseDefaultTargetUrl() || (targetUrlParameter != null && StringUtils.hasText(request.getParameter(targetUrlParameter)))) { requestCache.removeRequest(request, response); super.setAlwaysUseDefaultTargetUrl(false); super.setDefaultTargetUrl("/"); super.onAuthenticationSuccess(request, response, authentication); return; } //清除属性 clearAuthenticationAttributes(request); // Use the DefaultSavedRequest URL String targetUrl = savedRequest.getRedirectUrl(); logger.debug("Redirecting to DefaultSavedRequest Url: " + targetUrl); if(targetUrl != null && "".equals(targetUrl)){ targetUrl = LOCAL_SERVER_URL; } getRedirectStrategy().sendRedirect(request, response, targetUrl); } public void setRequestCache(RequestCache requestCache) { this.requestCache = requestCache; } } 5 认证失败控制类重写 /** * AuthenticationFailureHandler which performs a redirect to the value of the {@link #setDefaultFailureUrl * defaultFailureUrl} property when the onAuthenticationFailure method is called. * If the property has not been set it will send a 401 response to the client, with the error message from the * AuthenticationException which caused the failure. *

* If the {@code useForward} property is set, a {@code RequestDispatcher.forward} call will be made to * the destination instead of a redirect. * * @author Luke Taylor * @since 3.0 */ public class MySimpleUrlAuthenticationFailureHandler implements AuthenticationFailureHandler{ protected final Log logger = LogFactory.getLog(getClass()); private String defaultFailureUrl; private boolean forwardToDestination = false; private boolean allowSessionCreation = true; private RedirectStrategy redirectStrategy = new DefaultRedirectStrategy(); @Value(value = "${local.service.url}") private String LOCAL_SERVER_URL; public MySimpleUrlAuthenticationFailureHandler() { } public MySimpleUrlAuthenticationFailureHandler(String defaultFailureUrl) { setDefaultFailureUrl(defaultFailureUrl); } /** * Performs the redirect or forward to the {@code defaultFailureUrl} if set, otherwise returns a 401 error code. *

* If redirecting or forwarding, {@code saveException} will be called to cache the exception for use in * the target view. */ public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException { //认证失败区别前后台:LOGIN URL if(request.getParameter("spring-security-redirect") != null){ request.getSession().setAttribute("callUrlFailure", request.getParameter("spring-security-redirect")); } //若有loginUrl 则重定向到后台登录界面 if(request.getParameter("loginUrl") != null && !"".equals(request.getParameter("loginUrl"))){ defaultFailureUrl = LOCAL_SERVER_URL+"/backlogin.html?validated=false"; } //defaultFailureUrl 默认的认证失败回调URL if (defaultFailureUrl == null) { logger.debug("No failure URL set, sending 401 Unauthorized error"); response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Authentication Failed: " + exception.getMessage()); } else { saveException(request, exception); if (forwardToDestination) { logger.debug("Forwarding to " + defaultFailureUrl); request.getRequestDispatcher(defaultFailureUrl).forward(request, response); } else { logger.debug("Redirecting to " + defaultFailureUrl); redirectStrategy.sendRedirect(request, response, defaultFailureUrl); } } } /** * Caches the {@code AuthenticationException} for use in view rendering. *

* If {@code forwardToDestination} is set to true, request scope will be used, otherwise it will attempt to store * the exception in the session. If there is no session and {@code allowSessionCreation} is {@code true} a session * will be created. Otherwise the exception will not be stored. */ protected final void saveException(HttpServletRequest request, AuthenticationException exception) { if (forwardToDestination) { request.setAttribute(WebAttributes.AUTHENTICATION_EXCEPTION, exception); } else { HttpSession session = request.getSession(false); if (session != null || allowSessionCreation) { request.getSession().setAttribute(WebAttributes.AUTHENTICATION_EXCEPTION, exception); } } } /** * The URL which will be used as the failure destination. * * @param defaultFailureUrl the failure URL, for example "/loginFailed.jsp". */ public void setDefaultFailureUrl(String defaultFailureUrl) { this.defaultFailureUrl = defaultFailureUrl; } protected boolean isUseForward() { return forwardToDestination; } /** * If set to true, performs a forward to the failure destination URL instead of a redirect. Defaults to * false. */ public void setUseForward(boolean forwardToDestination) { this.forwardToDestination = forwardToDestination; } /** * Allows overriding of the behaviour when redirecting to a target URL. */ public void setRedirectStrategy(RedirectStrategy redirectStrategy) { this.redirectStrategy = redirectStrategy; } protected RedirectStrategy getRedirectStrategy() { return redirectStrategy; } protected boolean isAllowSessionCreation() { return allowSessionCreation; } public void setAllowSessionCreation(boolean allowSessionCreation) { this.allowSessionCreation = allowSessionCreation; } } 6 登录Controller和页面省略

 

你可能感兴趣的:(spring)