Spring Security integrate with SSO(Siteminder) spring securitySSOSiteminder
程序员文章站
2022-05-08 14:16:48
...
This is the sample to integrate SSO to Java web app with spring security, typical authentication process:
In this case, Web app sever is not proxyed, and recieve request directly, so the user's request arrive to Web app server firstly
Core Spring security config:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:sec="http://www.springframework.org/schema/security" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.1.xsd"> <sec:http pattern="/assets/**" security="none" /> <sec:http pattern="/views/logout**" security="none" /> <bean id="userDetailsService" class="com.wilson.security.CustomUserDetailsService" /> <sec:http entry-point-ref="loginHandler" use-expressions="true" auto-config="false" request-matcher="regex"> <sec:intercept-url pattern="/**" access="isAuthenticated()" /> <sec:logout logout-url="/logout" invalidate-session="true" success-handler-ref="logoutHandler" /> <sec:custom-filter ref="authenticationFilter" position="FORM_LOGIN_FILTER" /> </sec:http> <bean id="loginHandler" class="com.wilson.security.SSOLoginHandler"> <property name="loginFormUrl" value="${sso.proxy}" /> <property name="authProcessingURL" value="http://${fqdn}:${port}${context}/authenticate" /> </bean> <bean id="logoutHandler" class="com.wilson.security.SSOLogoutHandler"> <property name="defaultTargetUrl" value="/views/logout.jsp" /> <property name="alwaysUseDefaultTargetUrl" value="true" /> </bean> <bean id="authenticationFailureHandler" class="org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler"> <constructor-arg value="/views/logout-failure.jsp"></constructor-arg> </bean> <bean id="authenticationFilter" class="com.wilson.security.SSOAuthenticationFilter"> <property name="filterProcessesUrl" value="/authenticate" /> <property name="authenticationManager" ref="authenticationManager" /> <property name="AuthenticationFailureHandler" ref="authenticationFailureHandler" /> <property name="publicKey" value="${sso.publickey}" /> </bean> <sec:authentication-manager alias="authenticationManager"> <sec:authentication-provider user-service-ref="userDetailsService" /> </sec:authentication-manager> </beans>
So, first, we need to add a custom LoginUrlAuthenticationEntryPoint to redirect request to SSO when user open home page without login
public class SSOLoginHandler extends LoginUrlAuthenticationEntryPoint { private final Logger logger = LoggerFactory.getLogger(SSOLoginHandler.class); private String authProcessingURL; @Override public void commence(final HttpServletRequest request, final HttpServletResponse response, final AuthenticationException authenticationException) throws IOException, ServletException { logger.debug("Preparing redirectiion to SSO PROXY..."); // new DefaultRedirectStrategy().sendRedirect(request, response, this.getLoginFormUrl() + "?ref=" // + authProcessingURL); String SSO_LOGIN_URL= "https://ssoserver.com/sso.jsp"; new DefaultRedirectStrategy().sendRedirect(request, response, SSO_LOGIN_URL + "?ref=" + authProcessingURL); } public String getAuthProcessingURL() { return authProcessingURL; } public void setAuthProcessingURL(final String authProcessingURL) { this.authProcessingURL = authProcessingURL; }
Simplete logout which do some logging items..
public class SSOLogoutHandler extends SimpleUrlLogoutSuccessHandler { private final Logger logger = LoggerFactory.getLogger(SSOLogoutHandler.class); @Override public void onLogoutSuccess(final HttpServletRequest request, final HttpServletResponse response, final Authentication authentication) throws IOException, ServletException { super.onLogoutSuccess(request, response, authentication); logger.debug("Performing an SSO logout at: {}", this.getDefaultTargetUrl()); } }
Custom UserDeatailsService to load role and Grant Authority to user
public class CustomUserDetailsService implements UserDetailsService { public static final String DEFAULT_AUTH_PASSWORD = "password"; @Override public UserDetails loadUserByUsername(String soeid) throws UsernameNotFoundException { List<GrantedAuthority> grantedAuths = new ArrayList<GrantedAuthority>(); grantedAuths.add(new SimpleGrantedAuthority(***Service.queryUserRoleFromDatabase(soeid).toString())); UserDetails user = new User(soeid, DEFAULT_AUTH_PASSWORD, true, true, true, true, grantedAuths); return user; } }
Custom authetication filter to processe the response form SSO server after logicn
public class SSOAuthenticationFilter extends UsernamePasswordAuthenticationFilter { public static final String DEFAULT_AUTH_PASSWORD = "password"; private final Logger logger = LoggerFactory.getLogger(SSOAuthenticationFilter.class); private Cipher cipher; public SSOAuthenticationFilter() { super.setPostOnly(false); // allow a GET request from SSO PROXY } @Override public Authentication attemptAuthentication(final HttpServletRequest request, final HttpServletResponse response) throws AuthenticationException { String[] sid = decodeSID(request); String soeid = sid[0]; // token is expired if currentTimeMillis is greater then TIMESTAMP if (System.currentTimeMillis() > Long.parseLong(sid[1])) { logger.error("Authentication rejected for: {}", soeid); throw new NonceExpiredException("Authentication token is expired"); } // saving decoded SOEID in a REQUEST to reuse it by obtainUsername() request.setAttribute("SSO_USER_SOEID", soeid); return super.attemptAuthentication(request, response); } @Override protected String obtainPassword(final HttpServletRequest request) { return DEFAULT_AUTH_PASSWORD; } @Override protected String obtainUsername(final HttpServletRequest request) { //SM_USER is coming from SSO after login return (String) request.getAttribute("SM_USER"); } private String[] decodeSID(final HttpServletRequest request) { .............add SSO server decode strtegy } }
You may say above sample was not my case, what happens we have SSO setup in the proxy server as below?
only difference is in the login entry filter, we redirect to the web app authentication filter("/authenticate") as it's pre-logged in
public class SSOLoginHandler extends LoginUrlAuthenticationEntryPoint { private final Logger logger = LoggerFactory.getLogger(SSOLoginHandler.class); private String authProcessingURL; @Override public void commence(final HttpServletRequest request, final HttpServletResponse response, final AuthenticationException authenticationException) throws IOException, ServletException { logger.debug("Preparing redirectiion to SSO PROXY..."); new DefaultRedirectStrategy().sendRedirect(request, response, "/authenticate"); } }
上一篇: svn 创建 分支 branches
下一篇: hibernate的创建