• Spring Security 入门(3-11)Spring Security 的使用-自定义登录验证和回调地址


    1. 配置文件 security-ns.xml  
    2.      
    3.      <?xml version="1.0" encoding="UTF-8"?>  
    4.     <beans xmlns="http://www.springframework.org/schema/beans"  
    5.     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:security="http://www.springframework.org/schema/security"  
    6.     xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd  
    7.         http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.1.xsd">  
    8.   
    9.     //需要过滤不被拦截的请求  
    10.     <security:http pattern="/openapi/**" security="none" />  
    11.     <security:http pattern="/useraccounts/userprofile.json" security="none" />  
    12.     <security:http pattern="/useraccounts/register**" security="none" />  
    13.      
    14.      //entry-point-ref 配置自定义登录  
    15.     <security:http auto-config="false" entry-point-ref="authenticationEntryPoint">  
    16.         <security:intercept-url pattern="/backManage/**" access="ROLE_BACK_USER" />  
    17.         <security:intercept-url pattern="/mall/**"       access="ROLE_BACK_USER" />  
    18.         <security:intercept-url pattern="/thirdUser/**"  access="ROLE_USER" />  
    19.         <security:intercept-url pattern="/useraccounts/**" access="ROLE_USER" />  
    20.         <security:intercept-url pattern="/cart/**.html" access="ROLE_USER" />  
    21.         <security:intercept-url pattern="/ticket/**" access="ROLE_USER,ROLE_BACK_USER" />  
    22.         <security:intercept-url pattern="/order/**" access="ROLE_USER" />  
    23.         <security:intercept-url pattern="/comment/**" access="ROLE_USER" />  
    24.         <security:intercept-url pattern="/personal/**" access="ROLE_USER" />  
    25.         <security:intercept-url pattern="/favorite/**" access="ROLE_USER" />  
    26.       
    27.         //需要替换的Filter顺序,配置自定义custom-filter时必须蔣auto-config="false",不然会报已经存在同样的过滤器错误  
    28.         <security:custom-filter ref="myLoginFilter"  position="FORM_LOGIN_FILTER" />  
    29.         //登出配置  
    30.         <security:logout logout-success-url="${local.service.url}"/>  
    31.     </security:http>  
    32.   
    33.      //密码加密工具类  
    34.     <bean id="encoder" class="org.springframework.security.authentication.encoding.ShaPasswordEncoder"/>  
    35.     //认证管理器  
    36.     <security:authentication-manager alias="authenticationManager">  
    37.         //UserDetailsService实现 主要用于用户的查询  
    38.         <security:authentication-provider user-service-ref="userLoginService">  
    39.             <security:password-encoder  ref="encoder">  
    40.             </security:password-encoder>  
    41.         </security:authentication-provider>  
    42.     </security:authentication-manager>  
    43.   
    44.     <bean id="myLoginFilter" class="com.sale114.www.sercurity.MyUsernamePasswordAuthenticationFilter">  
    45.         <property name="authenticationManager" ref="authenticationManager"/>  
    46.         <property name="authenticationFailureHandler" ref="failureHandler"/>  
    47.         <property name="authenticationSuccessHandler" ref="successHandler"/>  
    48.     </bean>  
    49.   
    50.     //成功登录后  
    51.     <bean id="successHandler" class="com.sale114.www.sercurity.MySavedRequestAwareAuthenticationSuccessHandler">  
    52.         <property name="defaultTargetUrl" value="${local.service.url}"/>  
    53.     </bean>  
    54.     //登录失败  
    55.     <bean id="failureHandler" class="com.sale114.www.sercurity.MySimpleUrlAuthenticationFailureHandler">  
    56.         <property name="defaultFailureUrl" value="${local.service.url}/login.html?validated=false"/>  
    57.     </bean>  
    58.       
    59.     <bean id="authenticationEntryPoint"  
    60.         class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint">  
    61.         <property name="loginFormUrl" value="${local.service.url}/login.html" />  
    62.     </bean>  
    63. </beans>  
    64.   
    65.   
    66. 2 UserLoginServiceImpl 查询用户实现类  
    67.   
    68.      @Named("userLoginService")  
    69. public class UserLoginServiceImpl  implements UserDetailsService ,LoginService{  
    70.   
    71.     @Inject  
    72.     private UserLoginDAO userLoginDAO;  
    73.       
    74.     @Override  
    75.     public WrappedUserLogin getUserLogin() {  
    76.         try {  
    77.             WrappedUserLogin wrappedUserLogin = (WrappedUserLogin) SecurityContextHolder  
    78.                     .getContext().getAuthentication().getPrincipal();  
    79.             return wrappedUserLogin;  
    80.         } catch (Exception e) {  
    81.             return null;  
    82.         }  
    83.     }  
    84.   
    85.     @Override  
    86.     public UserDetails loadUserByUsername(String username)  
    87.             throws UsernameNotFoundException {  
    88.         System.out.println("用户名-------------"+username);  
    89.         UserLogin userLogin =  null;  
    90.         if(username != null && !"".equals(username)&& username.indexOf("@") > 0){  
    91.               userLogin = userLoginDAO.findByEmail(username);  
    92.               username = userLogin.getNick();  
    93.         }else{  
    94.             userLogin = userLoginDAO.findByNick(username);  
    95.         }  
    96.         System.out.println("user is null ---"+userLogin.getUserType());  
    97.         String nick = userLogin.getNick();  
    98.         String email = userLogin.getEmail();  
    99.         String mobile = userLogin.getMobile();  
    100.         int userType = userLogin.getUserType();  
    101.         List<GrantedAuthority> resultAuths = new ArrayList<GrantedAuthority>();  
    102.           
    103.   
    104.         // 前台用户  
    105.         if (userType == 1) {  
    106.             resultAuths.add(new SimpleGrantedAuthority("ROLE_USER"));  
    107.         } else {  
    108.             resultAuths.add(new SimpleGrantedAuthority("ROLE_BACK_USER"));  
    109.         }  
    110.           
    111.         return new WrappedUserLogin(userLogin.getId(), email, nick, mobile, userLogin.getPassword(), userType,resultAuths);  
    112.     }  
    113.   
    114. }  
    115.   
    116. 3 重写用户名密码验证  
    117.      public class MyUsernamePasswordAuthenticationFilter extends UsernamePasswordAuthenticationFilter{  
    118.         //用户名  
    119.         public static final String SPRING_SECURITY_FORM_USERNAME_KEY = "j_username";  
    120.         //密码  
    121.         public static final String SPRING_SECURITY_FORM_PASSWORD_KEY = "j_password";  
    122.         //需要回调的URL 自定义参数  
    123.         public static final String SPRING_SECURITY_FORM_REDERICT_KEY = "spring-security-redirect";  
    124.           
    125.         /**  
    126.          * @deprecated If you want to retain the username, cache it in a customized {@code AuthenticationFailureHandler}  
    127.          */  
    128.         @Deprecated  
    129.         public static final String SPRING_SECURITY_LAST_USERNAME_KEY = "SPRING_SECURITY_LAST_USERNAME";  
    130.   
    131.         private String usernameParameter = SPRING_SECURITY_FORM_USERNAME_KEY;  
    132.         private String passwordParameter = SPRING_SECURITY_FORM_PASSWORD_KEY;  
    133.         private String redirectParameter = SPRING_SECURITY_FORM_REDERICT_KEY;  
    134.         private boolean postOnly = true;  
    135.   
    136.         //~ Constructors ===================================================================================================  
    137.   
    138.         public MyUsernamePasswordAuthenticationFilter() {  
    139.            super();  
    140.         }  
    141.   
    142.         //~ Methods ========================================================================================================  
    143.   
    144.         public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {  
    145.             if (postOnly && !request.getMethod().equals("POST")) {  
    146.                 throw new AuthenticationServiceException("Authentication method not supported: " + request.getMethod());  
    147.             }  
    148.             String username = obtainUsername(request);  
    149.             String password = obtainPassword(request);  
    150.             String redirectUrl = obtainRedercitUrl(request);  
    151.             if (username == null) {  
    152.                 username = "";  
    153.             }  
    154.   
    155.             if (password == null) {  
    156.                 password = "";  
    157.             }  
    158.             //自定义回调URL,若存在则放入Session  
    159.             if(redirectUrl != null && !"".equals(redirectUrl)){  
    160.                 request.getSession().setAttribute("callCustomRediretUrl", redirectUrl);  
    161.             }  
    162.             username = username.trim();  
    163.             UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(username, password);  
    164.             // Allow subclasses to set the "details" property  
    165.             setDetails(request, authRequest);  
    166.             return this.getAuthenticationManager().authenticate(authRequest);  
    167.         }  
    168.   
    169.         /** 
    170.          * Enables subclasses to override the composition of the password, such as by including additional values 
    171.          * and a separator.<p>This might be used for example if a postcode/zipcode was required in addition to the 
    172.          * password. A delimiter such as a pipe (|) should be used to separate the password and extended value(s). The 
    173.          * <code>AuthenticationDao</code> will need to generate the expected password in a corresponding manner.</p> 
    174.          * 
    175.          * @param request so that request attributes can be retrieved 
    176.          * 
    177.          * @return the password that will be presented in the <code>Authentication</code> request token to the 
    178.          *         <code>AuthenticationManager</code> 
    179.          */  
    180.         protected String obtainPassword(HttpServletRequest request) {  
    181.             return request.getParameter(passwordParameter);  
    182.         }  
    183.   
    184.         /** 
    185.          * Enables subclasses to override the composition of the username, such as by including additional values 
    186.          * and a separator. 
    187.          * 
    188.          * @param request so that request attributes can be retrieved 
    189.          * 
    190.          * @return the username that will be presented in the <code>Authentication</code> request token to the 
    191.          *         <code>AuthenticationManager</code> 
    192.          */  
    193.         protected String obtainUsername(HttpServletRequest request) {  
    194.             return request.getParameter(usernameParameter);  
    195.         }  
    196.           
    197.           
    198.         protected String obtainRedercitUrl(HttpServletRequest request) {  
    199.             return request.getParameter(redirectParameter);  
    200.         }  
    201.   
    202.         /** 
    203.          * Provided so that subclasses may configure what is put into the authentication request's details 
    204.          * property. 
    205.          * 
    206.          * @param request that an authentication request is being created for 
    207.          * @param authRequest the authentication request object that should have its details set 
    208.          */  
    209.         protected void setDetails(HttpServletRequest request, UsernamePasswordAuthenticationToken authRequest) {  
    210.             authRequest.setDetails(authenticationDetailsSource.buildDetails(request));  
    211.         }  
    212.   
    213.         /** 
    214.          * Sets the parameter name which will be used to obtain the username from the login request. 
    215.          * 
    216.          * @param usernameParameter the parameter name. Defaults to "j_username". 
    217.          */  
    218.         public void setUsernameParameter(String usernameParameter) {  
    219.             Assert.hasText(usernameParameter, "Username parameter must not be empty or null");  
    220.             this.usernameParameter = usernameParameter;  
    221.         }  
    222.   
    223.         /** 
    224.          * Sets the parameter name which will be used to obtain the password from the login request.. 
    225.          * 
    226.          * @param passwordParameter the parameter name. Defaults to "j_password". 
    227.          */  
    228.         public void setPasswordParameter(String passwordParameter) {  
    229.             Assert.hasText(passwordParameter, "Password parameter must not be empty or null");  
    230.             this.passwordParameter = passwordParameter;  
    231.         }  
    232.   
    233.         /** 
    234.          * Defines whether only HTTP POST requests will be allowed by this filter. 
    235.          * If set to true, and an authentication request is received which is not a POST request, an exception will 
    236.          * be raised immediately and authentication will not be attempted. The <tt>unsuccessfulAuthentication()</tt> method 
    237.          * will be called as if handling a failed authentication. 
    238.          * <p> 
    239.          * Defaults to <tt>true</tt> but may be overridden by subclasses. 
    240.          */  
    241.         public void setPostOnly(boolean postOnly) {  
    242.             this.postOnly = postOnly;  
    243.         }  
    244.   
    245.       
    246. }  
    247.   
    248.   
    249.   
    250. 4 SimpleUrlAuthenticationSuccessHandler重写  
    251.      public class MySavedRequestAwareAuthenticationSuccessHandler extends SimpleUrlAuthenticationSuccessHandler{  
    252.      @Value(value = "${local.service.url}")  
    253.      private String LOCAL_SERVER_URL;  
    254.       
    255.      protected final Log logger = LogFactory.getLog(this.getClass());  
    256.   
    257.         private RequestCache requestCache = new HttpSessionRequestCache();  
    258.   
    259.         @Override  
    260.         public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,  
    261.                 Authentication authentication) throws ServletException, IOException {  
    262.             SavedRequest savedRequest = requestCache.getRequest(request, response);  
    263.             if (savedRequest == null) {  
    264.                 System.out.println("savedRequest is null ");  
    265.                 //用户判断是否要使用上次通过session里缓存的回调URL地址  
    266.                 int flag = 0;  
    267.                 //通过提交登录请求传递需要回调的URL callCustomRediretUrl  
    268.                 if(request.getSession().getAttribute("callCustomRediretUrl") != null && !"".equals(request.getSession().getAttribute("callCustomRediretUrl"))){  
    269.                     String url = String.valueOf(request.getSession().getAttribute("callCustomRediretUrl"));  
    270.                     //若session 存在则需要使用自定义回调的URL 而不是缓存的URL  
    271.                     super.setDefaultTargetUrl(url);  
    272.                     super.setAlwaysUseDefaultTargetUrl(true);  
    273.                     flag = 1;  
    274.                     request.getSession().setAttribute("callCustomRediretUrl", "");  
    275.                 }  
    276.                 //重设置默认URL为主页地址  
    277.                 if(flag  == 0){  
    278.                     super.setDefaultTargetUrl(LOCAL_SERVER_URL);  
    279.                 }  
    280.                 super.onAuthenticationSuccess(request, response, authentication);  
    281.                  
    282.                 return;  
    283.             }  
    284.             //targetUrlParameter 是否存在  
    285.             String targetUrlParameter = getTargetUrlParameter();  
    286.             if (isAlwaysUseDefaultTargetUrl() || (targetUrlParameter != null && StringUtils.hasText(request.getParameter(targetUrlParameter)))) {  
    287.                 requestCache.removeRequest(request, response);  
    288.                 super.setAlwaysUseDefaultTargetUrl(false);  
    289.                 super.setDefaultTargetUrl("/");  
    290.                 super.onAuthenticationSuccess(request, response, authentication);  
    291.                 return;  
    292.             }  
    293.             //清除属性  
    294.             clearAuthenticationAttributes(request);  
    295.             // Use the DefaultSavedRequest URL  
    296.             String targetUrl = savedRequest.getRedirectUrl();  
    297.             logger.debug("Redirecting to DefaultSavedRequest Url: " + targetUrl);  
    298.             if(targetUrl != null && "".equals(targetUrl)){  
    299.                 targetUrl = LOCAL_SERVER_URL;  
    300.             }  
    301.             getRedirectStrategy().sendRedirect(request, response, targetUrl);  
    302.         }  
    303.   
    304.         public void setRequestCache(RequestCache requestCache) {  
    305.             this.requestCache = requestCache;  
    306.         }  
    307. }  
    308.   
    309. 5 认证失败控制类重写  
    310. /** 
    311.  * <tt>AuthenticationFailureHandler</tt> which performs a redirect to the value of the {@link #setDefaultFailureUrl 
    312.  * defaultFailureUrl} property when the <tt>onAuthenticationFailure</tt> method is called. 
    313.  * If the property has not been set it will send a 401 response to the client, with the error message from the 
    314.  * <tt>AuthenticationException</tt> which caused the failure. 
    315.  * <p> 
    316.  * If the {@code useForward} property is set, a {@code RequestDispatcher.forward} call will be made to 
    317.  * the destination instead of a redirect. 
    318.  * 
    319.  * @author Luke Taylor 
    320.  * @since 3.0 
    321.  */  
    322. public class MySimpleUrlAuthenticationFailureHandler implements AuthenticationFailureHandler{  
    323.   
    324.     protected final Log logger = LogFactory.getLog(getClass());  
    325.   
    326.     private String defaultFailureUrl;  
    327.     private boolean forwardToDestination = false;  
    328.     private boolean allowSessionCreation = true;  
    329.     private RedirectStrategy redirectStrategy = new DefaultRedirectStrategy();  
    330.     @Value(value = "${local.service.url}")  
    331.     private String LOCAL_SERVER_URL;  
    332.       
    333.     public MySimpleUrlAuthenticationFailureHandler() {  
    334.     }  
    335.   
    336.     public MySimpleUrlAuthenticationFailureHandler(String defaultFailureUrl) {  
    337.         setDefaultFailureUrl(defaultFailureUrl);  
    338.     }  
    339.   
    340.     /** 
    341.      * Performs the redirect or forward to the {@code defaultFailureUrl} if set, otherwise returns a 401 error code. 
    342.      * <p> 
    343.      * If redirecting or forwarding, {@code saveException} will be called to cache the exception for use in 
    344.      * the target view. 
    345.      */  
    346.     public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response,  
    347.             AuthenticationException exception) throws IOException, ServletException {  
    348.         //认证失败区别前后台:LOGIN URL  
    349.         if(request.getParameter("spring-security-redirect") != null){  
    350.               request.getSession().setAttribute("callUrlFailure", request.getParameter("spring-security-redirect"));  
    351.         }  
    352.         //若有loginUrl 则重定向到后台登录界面  
    353.         if(request.getParameter("loginUrl") != null && !"".equals(request.getParameter("loginUrl"))){  
    354.             defaultFailureUrl = LOCAL_SERVER_URL+"/backlogin.html?validated=false";  
    355.         }  
    356.         //defaultFailureUrl 默认的认证失败回调URL  
    357.         if (defaultFailureUrl == null) {  
    358.             logger.debug("No failure URL set, sending 401 Unauthorized error");  
    359.             response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Authentication Failed: " + exception.getMessage());  
    360.         } else {  
    361.             saveException(request, exception);  
    362.             if (forwardToDestination) {  
    363.                 logger.debug("Forwarding to " + defaultFailureUrl);  
    364.                 request.getRequestDispatcher(defaultFailureUrl).forward(request, response);  
    365.             } else {  
    366.                 logger.debug("Redirecting to " + defaultFailureUrl);  
    367.                 redirectStrategy.sendRedirect(request, response, defaultFailureUrl);  
    368.             }  
    369.         }  
    370.     }  
    371.   
    372.     /** 
    373.      * Caches the {@code AuthenticationException} for use in view rendering. 
    374.      * <p> 
    375.      * If {@code forwardToDestination} is set to true, request scope will be used, otherwise it will attempt to store 
    376.      * the exception in the session. If there is no session and {@code allowSessionCreation} is {@code true} a session 
    377.      * will be created. Otherwise the exception will not be stored. 
    378.      */  
    379.     protected final void saveException(HttpServletRequest request, AuthenticationException exception) {  
    380.         if (forwardToDestination) {  
    381.             request.setAttribute(WebAttributes.AUTHENTICATION_EXCEPTION, exception);  
    382.         } else {  
    383.             HttpSession session = request.getSession(false);  
    384.   
    385.             if (session != null || allowSessionCreation) {  
    386.                 request.getSession().setAttribute(WebAttributes.AUTHENTICATION_EXCEPTION, exception);  
    387.             }  
    388.         }  
    389.     }  
    390.   
    391.     /** 
    392.      * The URL which will be used as the failure destination. 
    393.      * 
    394.      * @param defaultFailureUrl the failure URL, for example "/loginFailed.jsp". 
    395.      */  
    396.     public void setDefaultFailureUrl(String defaultFailureUrl) {  
    397.         this.defaultFailureUrl = defaultFailureUrl;  
    398.     }  
    399.   
    400.     protected boolean isUseForward() {  
    401.         return forwardToDestination;  
    402.     }  
    403.   
    404.     /** 
    405.      * If set to <tt>true</tt>, performs a forward to the failure destination URL instead of a redirect. Defaults to 
    406.      * <tt>false</tt>. 
    407.      */  
    408.     public void setUseForward(boolean forwardToDestination) {  
    409.         this.forwardToDestination = forwardToDestination;  
    410.     }  
    411.   
    412.     /** 
    413.      * Allows overriding of the behaviour when redirecting to a target URL. 
    414.      */  
    415.     public void setRedirectStrategy(RedirectStrategy redirectStrategy) {  
    416.         this.redirectStrategy = redirectStrategy;  
    417.     }  
    418.   
    419.     protected RedirectStrategy getRedirectStrategy() {  
    420.         return redirectStrategy;  
    421.     }  
    422.   
    423.     protected boolean isAllowSessionCreation() {  
    424.         return allowSessionCreation;  
    425.     }  
    426.   
    427.     public void setAllowSessionCreation(boolean allowSessionCreation) {  
    428.         this.allowSessionCreation = allowSessionCreation;  
    429.     }  
    430.   
    431. }  
  • 相关阅读:
    PowerDesigner 找不到Identity列的解决方法
    C# DataTable 和List之间相互转换的方法
    解决Win8无法升级.NET Framework 3.5.1 提示错误0x800F0906
    C#虚方法和抽象方法区别
    VS自带WCF测试客户端
    asp.net读取Excel数据
    输出用户的IP地址,并且判断用户的IP地址是否在192.168.1.100 --- 192.168.1.150之间
    验证电子邮箱正则表达式
    用PHP实现冒泡排序将数组$a=array()按照从小到大的方式排序
    打开a.txt文件在文件中最前面加上hello
  • 原文地址:https://www.cnblogs.com/lexiaofei/p/7018818.html
Copyright © 2020-2023  润新知