Spring security 集成单独登录常见的CAS, 这在后面的博客中再写,这里记录一下简单的单点登录的Client处理
这里我们要用到PRE_AUTH_FILTER这个过滤器,扩展AbstractPreAuthenticatedProcessingFilter实现自己的登录验证;
验证管理器要用到 PreAuthenticatedAuthenticationProvider
上配置
<security:http auto-config="false" use-expressions="false" entry-point-ref="ssoAuthenticationEntryPoint">
<security:custom-filter before="FILTER_SECURITY_INTERCEPTOR" ref="metadataSourceFilter" />
<security:access-denied-handler error-page="/ssoLogin.jsp"/>
<security:custom-filter position="PRE_AUTH_FILTER" ref="ssoAuthenticatedFilter" />
<security:custom-filter position="LOGOUT_FILTER" ref="ssoLogoutFilter" />
<security:custom-filter ref="usernamePasswordFilter" position="FORM_LOGIN_FILTER" />
<security:csrf disabled="true"/>
<security:headers>
<security:frame-options disabled="true" /> <!--policy="SAMEORIGIN" iframe安全等级-->
</security:headers>
</security:http>
<!--SSO验证入口-->
<bean id="ssoAuthenticationEntryPoint" class="com.XX.eip.saif.security.SSOAuthenticationEntryPoint">
<property name="loginUrl" value="/ssoLogin.jsp" /> <!-- //SSO登录地址 -->
</bean>
<!--SSO认证过滤器-->
<bean id="ssoAuthenticatedFilter" class="com.XX.eip.saif.security.SSOAuthenticatedFilter">
<property name="securityKey" value="1234556" />
<property name="securityIV" value="Qasdfasdf=" />
<property name="authenticationManager" ref="authenticationManager" />
</bean>
<!--验证管理器 只能定义一个-->
<security:authentication-manager alias="authenticationManager" > <!--erase-credentials="false" -->
<!--SSO验证管理器-->
<security:authentication-provider ref="authenticationProvider"/>
</security:authentication-manager>
<!--SSO用户验证器-->
<bean id="authenticationProvider" class="org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationProvider">
<property name="preAuthenticatedUserDetailsService" ref="authenticationUserDetailsService"/>
</bean>
<bean id="authenticationUserDetailsService" class="org.springframework.security.core.userdetails.UserDetailsByNameServiceWrapper">
<property name="userDetailsService" ref="userDetailsServiceImpl"/>
</bean>
<bean id="userDetailsServiceImpl" class="com.XX.platform.security.UserDetailsServiceImpl"/>
<!--sso登出拦截器-->
<bean id="ssoLogoutFilter" class="org.springframework.security.web.authentication.logout.LogoutFilter">
<constructor-arg value="/ssoLogout.jsp"/>
<constructor-arg>
<bean class="org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler"/>
</constructor-arg>
</bean>
<!--intercept-url过滤器-->
<bean id="metadataSourceFilter" class="com.XX.platform.security.MetadataSourceSecurityInterceptor">
<property name="authenticationManager" ref="authenticationManager" />
<property name="accessDecisionManager" ref="accessDecisionManager" />
<property name="securityMetadataSource" ref="metadataSource" />
</bean>
<bean id="accessDecisionManager" class="com.XX.platform.security.AccessDecisionManager"/>
<bean id="metadataSource" init-method="loadResourceConfig" class="com.XX.platform.security.MetadataSource"/>
<bean id="csrfTokenRepository" class="org.springframework.security.web.csrf.HttpSessionCsrfTokenRepository" />
<bean id="csrfRequiresMatcher" class="com.XX.platform.security.CsrfRequiresMatcher" />
<bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
<property name="basename" value="classpath:config/messages-security" />
</bean>
重要的需要自己写的过滤器只有一个PRE_AUTH_FILTER
public class SSOAuthenticatedFilter extends AbstractPreAuthenticatedProcessingFilter {
private String securityKey;
private String securityIV;
@Override
protected Object getPreAuthenticatedPrincipal(HttpServletRequest request) {
if (checkSource(request)){
String userIdentity = request.getParameter("UserIdentity");
return getLoginName(userIdentity);
}else {
return null;
}
}
@Override
protected Object getPreAuthenticatedCredentials(HttpServletRequest request) {
return checkSource(request) ? "N/A" : null;
}
private boolean checkSource(HttpServletRequest request){
if (!request.getRequestURI().equals("/")){
return false;
}
if (!request.getMethod().equals("POST")){
return false;
}
if (!request.getParameterMap().containsKey("SSOAction")){
return false;
}
if (!request.getParameterMap().containsKey("UserIdentity")){
return false;
}
return true;
}
private String getLoginName(String userIdentity){
String strDecrypt;
try {
strDecrypt = DES64Util.decrypt(userIdentity, this.securityKey, this.securityIV);
} catch (Exception e) {
Logger.error(e.getMessage(), e, SSOAuthenticatedFilter.class);
return "";
}
int iSplit = strDecrypt.indexOf("&");
int iSplit2 = strDecrypt.indexOf("=");
String loginName = strDecrypt.substring(iSplit2+1, iSplit);
return loginName;
}
public String getSecurityKey() {
return securityKey;
}
public void setSecurityKey(String securityKey) {
Assert.hasText(securityKey, "credentialsRequestHeader must not be empty or null");
this.securityKey = securityKey;
}
public String getSecurityIV() {
return securityIV;
}
public void setSecurityIV(String securityIV) {
Assert.hasText(securityIV, "securityIV must not be empty or null");
this.securityIV = securityIV;
}
}