Spring Security's Form-login provides Default-target-url as a login success after the jump address, but did not allow the passing of a RedirectURL parameter as a successful jump address.
The same logout label provides Logout-success-url as a successful exit after the jump address, nor does it provide permission to pass RedirectURL parameters to jump.
Originally intended to implement themselves and Adminauthsuccesshandler and Logoutsuccesshandler to receive the RedirectURL parameters to jump, the result view spring security code accidentally found spring Security actually provides targeturlparameter as a jump address parameter, but the security namespace does not have related tags or attributes. So after reading the jump-related code, I wrote the following configuration.
Note: If the direct permission to pass RedirectURL as a jump address, there will be a certain security risk. Make sure RedirectURL is trusted before use. The following configuration has a certain security risks.
The code is as follows |
Copy Code |
<sec:http auto-config= "true" > <sec:intercept-url pattern= "/admin/login" access= "is_authenticated_anonymously"/> <sec:form-login login-page= "/admin/login" authentication-failure-handler-ref= "AdminAuthFailureHandler" authentication-success-handler-ref= "Adminauthsuccesshandler"/> <sec:logout success-handler-ref= "Adminlogoutsuccesshandler"/> <sec:remember-me data-source-ref= "Jobdatasource"/> <sec:session-management> <sec:concurrency-control error-if-maximum-exceeded= "true" max-sessions= "1"/> </sec:session-management> </sec:http>
<bean id= "Adminauthfailurehandler" class= "Com.snsxiu.job.handler.AdminAuthFailureHandler" > <property name= "Authenticationfailureurl" value= "/admin/login?error=true"/> </bean>
<bean id= "Adminauthsuccesshandler" class= " Org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler "> <property name= "Targeturlparameter" value= "Target-url"/> <property name= "Defaulttargeturl" value= "/admin/index"/> </bean>
<bean id= "Adminlogoutsuccesshandler" class= " Org.springframework.security.web.authentication.logout.SimpleUrlLogoutSuccessHandler "> <property name= "Targeturlparameter" value= "Target-url"/> <property name= "Defaulttargeturl" value= "/admin/login"/> </bean> |
By looking at the source, we found that Simpleurllogoutsuccesshandler continued the Abstractauthenticationtargeturlrequesthandler, The same savedrequestawareauthenticationsuccesshandler also inherited the Abstractauthenticationtargeturlrequesthandler, In the handle method of Abstractauthenticationtargeturlrequesthandler, we find that it is through the Determinetargeturl () method to determine the redirect address.
code is as follows |
copy code |
public class Simpleurllogoutsuccesshandler extends Abstractauthenticationtargeturlrequesthandler implements Logoutsuccesshandler { public void onlogoutsuccess ( HttpServletRequest request, HttpServletResponse response, authentication authentication) throws IOException, servletexception { Super.handle (Request, response, authentication); } } |
Through analysis Determinetargeturl We draw the following conclusions:
① If Alwaysusedefaulttargeturl is true, the jump address is always defaulttargeturl
② if Targeturlparameter is not null, get the jump address from request Targeturlparameter the specified parameter name
③ if Usereferer is true and the first two steps are not obtained to the jump address, get the jump address from the Referer in the request header
④ If the above steps are empty, use the set Defaulttargeturl as the jump address
The default value for ⑤defaulttargeturl is "/"
In the final jump, spring security uses a redirectstrategy strategy to jump, typically using defaultredirectstrategy to jump, You can also implement your own redirectstrategy and configure it in the Adminauthsuccesshandler bean definition.
At the beginning we said, "If you allow RedirectURL to be passed directly as a jump address, there will be a certain security risk." If someone through your login or logout pass RedirectURL parameters misleading users to jump to the virus trojan site, then this is definitely your security do not enough, in order to secure us, we need to implement their own saferedirectstrategy, as shown below, A whitelist checksum was made to the URL before the jump.
The code is as follows |
Copy Code |
/** * Safe Redirectstrategy, mainly to determine whether the jump address in the white list * @author Guoweiwei gww0426@163.com * */ public class Saferedirectstrategy implements Redirectstrategy {
Protected final Log logger = Logfactory.getlog (GetClass ());
Private Boolean contextrelative;
/** * Redirects the response to the supplied URL. * <p> * If <tt>contextRelative</tt> is set, the redirect value would be the value of the request context path. Note * that this would result in the loss of protocol information (HTTP or HTTPS), so would cause problems if a * Redirect is being performed to? HTTPS, for example. */ public void Sendredirect (HttpServletRequest request, httpservletresponse response, String URL) throws IOException { String RedirectURL = Calculateredirecturl (Request.getcontextpath (), URL);
try { if (Urlutils.isabsoluteurl (RedirectURL)) { RedirectURL = Urlutil.buildredirectlink (RedirectURL, false); } catch (Exception e) { throw new IOException ("Error redirect URL", e); }
RedirectURL = Response.encoderedirecturl (RedirectURL);
if (logger.isdebugenabled ()) { Logger.debug ("Redirecting to" "+ RedirectURL +" "); }
Response.sendredirect (RedirectURL); }
private string Calculateredirecturl (string contextpath, string url) { if (! Urlutils.isabsoluteurl (URL)) { if (contextrelative) { return URL; } else { return contextpath + URL; } }
Full URL, including HTTP (s)://
if (!contextrelative) { return URL; }
Calculate the relative URL from the fully qualified URL, minus the scheme and base context. url = url.substring (Url.indexof ("://") + 3); Strip off scheme url = url.substring (Url.indexof (contextpath) + contextpath.length ());
if (Url.length () > 1 && url.charat (0) = = '/') { url = url.substring (1); }
return URL; }
/** * If <tt>true</tt>, causes any redirection URL to is calculated minus the protocol * and Context path (defaults to <tt>false</tt>). */ public void Setcontextrelative (Boolean userelativecontext) { This.contextrelative = Userelativecontext; }
} |
The code above urlutil a URL-handling tool for itself, Buildredirectlink will make a whitelist checksum of the URL. Don't forget to add saferedirectstrategy to the Servlet.xml bean configuration. As shown below:
The code is as follows |
Copy Code |
<bean id= "Adminauthsuccesshandler" class= " Org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler "> <property name= "Targeturlparameter" value= "Target-url"/> <property name= "Defaulttargeturl" value= "/admin/index"/> <property name= "Redirectstrategy" ref= "Saferedirectstrategy"/> </bean>
<bean id= "Adminlogoutsuccesshandler" class= " Org.springframework.security.web.authentication.logout.SimpleUrlLogoutSuccessHandler "> <property name= "Targeturlparameter" value= "Target-url"/> <property name= "Defaulttargeturl" value= "/admin/login"/> <property name= "Redirectstrategy" ref= "Saferedirectstrategy"/> </bean>
<bean id= "Saferedirectstrategy" class= "Com.snsxiu.job.web.security.SafeRedirectStrategy"/> |