spring security4 之 SSO

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;
    }
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值