- 描述問題
瀏覽器中輸入http://localhost:8080/test.html,認證服務跳轉到login.html,輸入正確的賬號密碼後,跳轉過去返回404。
- 分析問題
pom主要信息
spring boot version 2.0.4.RELEASE
spring security 、MVC version 2.0.4.RELEASE
仔細看了最後跳轉的路徑,是根路徑“\”,和初衷test.html天壤之別。
@Component("mSuccessHandler")
public class CustomAuthenticationSuccesstHandler extends SimpleUrlAuthenticationSuccessHandler {
@Override
public void onAuthenticationSuccess(HttpServletRequest request
, HttpServletResponse response
, Authentication authentication)
throws IOException, ServletException {
super.onAuthenticationSuccess(request, response, authentication);
}
}
}
查看源碼super.OnAuthenticationSuccess(request,response,authentication);
public class SimpleUrlAuthenticationSuccessHandler extends AbstractAuthenticationTargetUrlRequestHandler implements AuthenticationSuccessHandler {
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
this.handle(request, response, authentication);
this.clearAuthenticationAttributes(request);
}
}
繼續this.handle(request,response,authentication);
public abstract class AbstractAuthenticationTargetUrlRequestHandler {
protected void handle(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
String targetUrl = this.determineTargetUrl(request, response);
if (response.isCommitted()) {
this.logger.debug("Response has already been committed. Unable to redirect to " + targetUrl);
} else {
this.redirectStrategy.sendRedirect(request, response, targetUrl);
}
}
protected String determineTargetUrl(HttpServletRequest request, HttpServletResponse response) {
if (this.isAlwaysUseDefaultTargetUrl()) {
return this.defaultTargetUrl;
} else {
String targetUrl = null;
if (this.targetUrlParameter != null) {
targetUrl = request.getParameter(this.targetUrlParameter);
if (StringUtils.hasText(targetUrl)) {
this.logger.debug("Found targetUrlParameter in request: " + targetUrl);
return targetUrl;
}
}
if (this.useReferer && !StringUtils.hasLength(targetUrl)) {
targetUrl = request.getHeader("Referer");
this.logger.debug("Using Referer header: " + targetUrl);
}
if (!StringUtils.hasText(targetUrl)) {
targetUrl = this.defaultTargetUrl;
this.logger.debug("Using default Url: " + targetUrl);
}
return targetUrl;
}
}
}
繼續 this.determineTargetUrl(request, response);
target有三種被修改的可能方式:
1.targetUrlParameter不等於空
targetUrlParameter這是個成員屬性,可以通過public void setTargetUrlParameter(String targetUrlParameter) {......}設置,而後targetUrl = request.getParameter(this.targetUrlParameter);
那麼如何處理才能得到這個tergetUri呢?requestParameter該方法就是根據http上傳的參數,而後獲取其值。這裏我本想通過request設置其值,但是request不支持setParameter這個方法,個人猜想也是爲了保護該次請求唯一性吧。
假設可以通過某些方式,成功添加了請求參數,除非約束了請求跳轉的參數名字,否則
targetUrl = request.getParameter(this.targetUrlParameter); 這個this.targetUriParameter也是個棘手的事情。
2. targetUrl = request.getHeader("Referer");通過header.Refer
同前者一樣,request不支持setHeader一些api。
3.targetUrl = this.defaultTargetUrl;
前兩種情況都爲空的時候,只能使用默認的Uri,也就是跳轉後報404的結果的路徑“\”。
- 解決問題
package com.fosun.springsecurity.authentication;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fosun.springsecurity.properties.LoginType;
import com.fosun.springsecurity.properties.SecurityProperties;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler;
import org.springframework.security.web.savedrequest.HttpSessionRequestCache;
import org.springframework.security.web.savedrequest.RequestCache;
import org.springframework.security.web.savedrequest.SavedRequest;
import org.springframework.stereotype.Component;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* @author: Christ
* @date: 2018/8/16 11:18
* @desc:
*/
@Component("mAuthSuccessHandler")
public class CustomerAuthenticationSuccessRedirectHandler extends SimpleUrlAuthenticationSuccessHandler {
private static final Logger logger = LoggerFactory.getLogger(CustomerAuthenticationSuccessRedirectHandler.class);
@Autowired
private ObjectMapper objectMapper;
@Autowired
private SecurityProperties securityProperties;
private RequestCache requestCache = new HttpSessionRequestCache();
@Override
public void onAuthenticationSuccess(HttpServletRequest request
, HttpServletResponse response
, Authentication authentication)
throws IOException, ServletException {
logger.info("登錄成功");
if(securityProperties.getBrowser().getLoginType() == LoginType.JSON){
response.setContentType("application/json;charset=utf-8");
response.getWriter().write(objectMapper.writeValueAsString(authentication));
}else{
SavedRequest savedRequest = requestCache.getRequest(request,response);
String targetUrl = savedRequest.getRedirectUrl();
getRedirectStrategy().sendRedirect(request,response,targetUrl);
clearAuthenticationAttributes(request);
}
}
}
- 結語
如果哪位同行有更好的建議和方法,還望不吝賜教。