Spring Security integrate with SSO(Siteminder)

This is the sample to integrate SSO to Java web app with spring security, typical authentication process:


[b]In this case, Web app sever is not proxyed, and recieve request directly, so the user's request arrive to Web app server firstly[/b]
[img]http://dl2.iteye.com/upload/attachment/0118/8617/b986decd-5d80-3e48-bc95-2a924ab06067.jpg[/img]

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
}

}


[b]
You may say above sample was not my case, what happens we have SSO setup in the proxy server as below?[/b]
[img]http://dl2.iteye.com/upload/attachment/0118/8615/2525dae2-ee24-3ee0-98fe-e58799aa33b7.jpg[/img]

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

}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值