spring security 整合sso全記錄

@[TOC](spring security 整合sso全記錄)

# 介紹一下我司的sso流程

我司的sso流程:

1。 app在sso系統註冊想被sso攔截的sso url, 本app註冊了app/index

2。 sso會在公司閘道器層攔截 app/index的url,根據使用者cookie是否攜帶正確token,決定是否觸發登入流程(如果已經登入,則直接放行到(app/index),如果沒有登入,則轉發到全司統一的sso登入頁面)

3。 sso驗證通過後,會重定向到app(app/index),app可以拿到使用者登入資訊

# app security 整合sso的思路

1。 app對使用者提交的請求路徑,利用spring security 判斷使用者是否登入,如未登入,則重定向到app/index, sso會在閘道器層抓到這個url,從而觸發sso登入流程。

2。 登入成功後,app拿到登入資訊(userid等),設定認證透過,獲取user在本app的角色等資訊,並儲存到security。

3。 登入成功後的使用者,再次訪問app時,app就可以利用spring security判斷使用者是否登入了。

## 要解決的問題

1。 可以看出,本案例中其實不需要spring security預設提供的登入頁面,我們要讓security知道我們想要跳轉的登入url是app/index(POST方法)

2。 sso登入成功後,會跳轉回到我們的app url(app/index,GET方法)。怎麼讓security知道,並啟動spring security的認證流程?

3。 重寫security的驗證方法attemptAuthentication, 我們認為透過sso登入成功後,就預設登入app是驗證透過的。

4。 由於app是採用的前臺loadbalance+後臺機器叢集的方式。前臺的loadballance方式,由於我司流程,不能設定sticky session。 所以需採用springsession(redis)的方式

# 上程式碼

1。 解決第一個問題,很簡單,在spring-security。xml裡面配置

2。 第二個問題的解決稍微複雜一點:

我們要重寫驗證流程,是顯而易見的。於是,新建cMToolAuthenticationFilter extends UsernamePasswordAuthenticationFilter

xml配置如下

在CMToolAuthenticationFilter裡面,增加initCMAuFilter方法,指定觸發security驗證流程的url:/app/index

public class CMToolAuthenticationFilter extends UsernamePasswordAuthenticationFilter { @PostConstruct public void initCMAuFilter(){ //這裡指定觸發security驗證流程的url:/app/index RequestMatcher requiresAuthenticationRequestMatcher = new AntPathRequestMatcher(“/app/index”, “GET”); this。setRequiresAuthenticationRequestMatcher(requiresAuthenticationRequestMatcher); //這裡可以順便指定一下,登入成功後的自定義handler=>CMToolSuccessHandler this。setAuthenticationSuccessHandler(new CMToolSuccessHandler(“/cmtv1web/home”,userAuthenticateService)); }@Override public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException { //寫你自己的登入驗證邏輯 。。。。。 UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken( username, “”); setDetails(request, authRequest); return super。getAuthenticationManager()。authenticate(authRequest); } //指定authenticationManager @Override public void setAuthenticationManager(AuthenticationManager authenticationManager) { super。setAuthenticationManager(authenticationManager); }

```

CMToolAuthenticationProvider

```

@Autowired UserAuthenticateService userAuthenticateService; @Override public Authentication authenticate(Authentication authentication) throws AuthenticationException { String username = authentication。getName(); List authorities = new ArrayList(); //寫自己的一些給使用者加角色的邏輯 UserBean userBean = userAuthenticateService。getUser(username); if(userBean!=null) { //將user的角色交給spring security備用 List roles = userBean。getRoles(); if(roles!=null&&roles。size()>0){ for(RoleBean role:roles){ authorities。add(new SimpleGrantedAuthority(role。getRole_name())); } } } return new UsernamePasswordAuthenticationToken(username, “”, authorities); } @Override public boolean supports(Class<?> authentication) { return authentication。isAssignableFrom(UsernamePasswordAuthenticationToken。class); }

```

spring session redis的整合, 有時間再寫吧!