1. 程式人生 > >Spring Security整合Cas後頁面跳轉問題

Spring Security整合Cas後頁面跳轉問題

問題描述:在整合cas後,如果在A應用裡面直接呼叫B應用的某個頁面,第一次點選的時候總是會跳轉到B應用設定的預設頁面,然後再點選的時候,才能跳轉到正確的頁面。

後來通過檢視原始碼,發現
類:org.springframework.security.web.authentication.AbstractAuthenticationTargetUrlRequestHandler

protected String determineTargetUrl(HttpServletRequest request, HttpServletResponse response) {
if (isAlwaysUseDefaultTargetUrl()) {
return defaultTargetUrl;
}

// Check for the parameter and use that if available
String targetUrl = request.getParameter(targetUrlParameter);
......
}

這個方法首先會判斷是否設定了一直訪問預設頁面,如果false,則先獲取request裡面是否存在spring-security-redirect的引數,這個地址就是真正要跳轉的URL;
	<!-- cas 認證成功控制器 -->
<beans:bean id="authenticationSuccessHandler"
class="org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler">
<beans:property name="alwaysUseDefaultTargetUrl" value="false" />
<beans:property name="defaultTargetUrl" value="/index.htm" />
</beans:bean>

這個配置改好後,接下這是怎麼把spring-security-redirect帶到url後面了,再看這個類CasAuthenticationEntryPoint
類:org.springframework.security.cas.web.CasAuthenticationEntryPoint
public final void commence(final HttpServletRequest servletRequest, final HttpServletResponse response,
final AuthenticationException authenticationException) throws IOException, ServletException {

final String urlEncodedService = createServiceUrl(servletRequest, response);
final String redirectUrl = createRedirectUrl(urlEncodedService);

preCommence(servletRequest, response);

response.sendRedirect(redirectUrl);
}

protected String createServiceUrl(final HttpServletRequest request, final HttpServletResponse response) {
return CommonUtils.constructServiceUrl(null, response, this.serviceProperties.getService(), null, this.serviceProperties.getArtifactParameter(), this.encodeServiceUrlWithSessionId);
}

這是驗證未登入後,構建跳轉的頁面和引數(也就是登入頁面)的處理方法,那在這裡可以寫一個類繼承CasAuthenticationEntryPoint,重寫createServiceUrl方法,spring-security-redirect的引數拼到redirectUrl後面,並且將當前請求url獲取到;
自定義類:CasAuthenticationRedirect
public class CasAuthenticationRedirect extends CasAuthenticationEntryPoint{

private String serviceUrlBak=null;

@Override
protected String createServiceUrl(final HttpServletRequest request, final HttpServletResponse response) {
if(serviceUrlBak==null)
serviceUrlBak=getServiceProperties().getService();
if(serviceUrlBak!=null){
String ctx=request.getContextPath();
String queryString=request.getQueryString();
String requestURI=request.getRequestURI();
requestURI=requestURI.substring(requestURI.indexOf(ctx)+ctx.length(),requestURI.length());
String serviceUrl="";
if(!requestURI.equals("/") && requestURI.length()>0){
serviceUrl="?"+AbstractAuthenticationTargetUrlRequestHandler.DEFAULT_TARGET_PARAMETER;
serviceUrl+="="+requestURI;
if(StringUtils.isNotBlank(queryString)){
serviceUrl+="?"+queryString;
}
}
getServiceProperties().setService(serviceUrlBak+serviceUrl);
}
return super.createServiceUrl(request, response);
}
}

最後再將配置改一下:
<beans:bean id="casEntryPoint" class="net.assertion.CasAuthenticationRedirect">
......
</beans:bean>

這樣就OK了, 這是目前找到最簡單的解決方法了,不過,感覺既然spring提供了spring-security-redirect這個引數,應該會有相應的配置可以實現這個功能吧,哎...,主要是英文文件看不懂......