# 单点登出

# 一、前置条件

项目请参考client-springboot、client-oauth2

# 二、集成方式及说明【重要】

退出分成2中类型:主动退出、被动退出。

主动退出就是在平台上点击退出按钮,整个的退出cas。

但是,因为登陆时缓存了用户信息,我们还需要有一个接口,用于让平台调用,将我们缓存的用户清理掉。

# 1、主动登出

整体思路:

  • 前端发起/logout请求给后端。
  • 接收到请求后,获取session和cookie并清空里面信息,保证客户端会话被清空。
  • 从配置文件里获取CAS Server服务器URL,向CAS服务端发起注销请求保证cas登出。

关键代码

配置 application.yml

# cas客户端配置
cas:
  # CAS-server 域名+contentPath
  server-url-prefix: http://127.0.0.1:8000/cas
  # 我当前应用访问地址
  client-host-url: http://127.0.0.1:8100
1
2
3
4
5
6

关键代码 IndexController.java

/**
* cas配置信息
*/
@Autowired
CasClientConfigurationProperties casProperties;


/**
* 退出方法
* @param request
* @param response
* @return
*/
@RequestMapping(value = {"/logout"})
public String logout(HttpServletRequest request, HttpServletResponse response) {
  System.out.println("logout");

  //1 session过期
  HttpSession session = request.getSession(false);
  if (session != null) {
    // 过期会话
    session.invalidate();
  }

  //2 清除本地cookie
  // 获取Cookies数组
  Cookie[] cookies = request.getCookies();
  // 迭代查找并清除Cookie
  for (Cookie cookie: cookies) {
    //将cookie.setMaxAge(0)表示删除cookie.
    cookie.setMaxAge(0);
    cookie.setPath("/");
    response.addCookie(cookie);
  }

  //3 保证cas登出
  //3.1 可以直接登出,跳转到  "redirect:http://cas.server.com/cas/logout"
  //3.2 或是指定service,在跳转到某个位置。
  String encodedUrl;
  try {
    encodedUrl = URLEncoder.encode(casProperties.getClientHostUrl(), "UTF-8").replace("+", "%20");
  } catch (UnsupportedEncodingException e) {
    e.printStackTrace();
    encodedUrl = "";
  }
  String result = "redirect:" + casProperties.getServerUrlPrefix() + "/logout?service=" + encodedUrl;
  return result;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48

# 2、被动登出

# 以cas-client方式集成时的被动退出

添加配置类CasConfig.java

/**
 * cas客户端必要配置。处理被动退出。
 */
@Configuration
public class CasConfig {

    /**
     * cas配置信息
     */
    @Autowired
    CasClientConfigurationProperties casProperties;

    /**
     * 该过滤器用于实现单点登出功能,可触发服务端退出时,所有客户端的退出效果。
     * 单点退出配置,一定要放在其他filter之前
     */
    @Bean
    public FilterRegistrationBean singleSignOutFilter() {
        FilterRegistrationBean filterRegistration = new FilterRegistrationBean();
        filterRegistration.setFilter(new SingleSignOutFilter());
        filterRegistration.setEnabled(true);
        filterRegistration.addUrlPatterns("/*" );
        //CAS服务器的url前缀
        filterRegistration.addInitParameter("casServerUrlPrefix" , casProperties.getServerUrlPrefix());
      	//CAS服务器上配置的注销回调路径
        filterRegistration.addInitParameter("logoutCallbackPath" , "/logout");
        filterRegistration.setOrder(1);
        return filterRegistration ;
    }
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

# 以oauth2方式集成时的被动退出

	/**
     * 【主动】退出方法
     * @param request
     * @param response
     * @return
     */
    @RequestMapping(value = {"/logout"})
    public String logout(HttpServletRequest request, HttpServletResponse response) {
        System.out.println("logout");

        //1 session过期
        HttpSession session = request.getSession(false);
        if (session != null) {
            // 过期会话
            session.invalidate();
        }

        //2 清除本地cookie
        // 获取Cookies数组
        Cookie[] cookies = request.getCookies();
        // 迭代查找并清除Cookie
        for (Cookie cookie : cookies) {
            //将cookie.setMaxAge(0)表示删除cookie.
            cookie.setMaxAge(0);
            cookie.setPath("/");
            response.addCookie(cookie);
        }

        //3 保证cas登出
        //3.1 可以直接登出,跳转到  "redirect:http://cas.server.com/cas/logout"
        //3.2 或是指定service,在跳转到某个位置。
        String encodedUrl = ConvertUtil.urlEncode(sinoOauthConfig.getServerUrl() + "/index.jsp");
        String result = "redirect:" + sinoOauthConfig.getCasServerUrl() + "/logout?service=" + encodedUrl;
        return result;
    }


    /**
     * 【被动】退出方法
     * @param request
     * @param response
     */
    @RequestMapping(value = {"/passiveLogout"})
    @ResponseBody
    public void passiveLogout(HttpServletRequest request, HttpServletResponse response) {
        System.out.println("passiveLogout");

        SessionUtil.destroySession(request);
        SessionUtil.getSessions();
    }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50