Commit ab40254bc1591644394e07f34762eef2a598cc53

Authored by YunaiV
1 parent ff54f169

完成 yudao-sso-demo-by-code 退出登录

yudao-example/yudao-sso-demo-by-code/src/main/java/cn/iocoder/yudao/ssodemo/client/OAuth2Client.java
... ... @@ -121,6 +121,32 @@ public class OAuth2Client {
121 121 return exchange.getBody();
122 122 }
123 123  
  124 + /**
  125 + * 删除访问令牌
  126 + *
  127 + * @param token 访问令牌
  128 + * @return 成功
  129 + */
  130 + public CommonResult<Boolean> revokeToken(String token) {
  131 + // 1.1 构建请求头
  132 + HttpHeaders headers = new HttpHeaders();
  133 + headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
  134 + headers.set("tenant-id", TENANT_ID.toString());
  135 + addClientHeader(headers);
  136 + // 1.2 构建请求参数
  137 + MultiValueMap<String, Object> body = new LinkedMultiValueMap<>();
  138 + body.add("token", token);
  139 +
  140 + // 2. 执行请求
  141 + ResponseEntity<CommonResult<Boolean>> exchange = restTemplate.exchange(
  142 + BASE_URL + "/token",
  143 + HttpMethod.DELETE,
  144 + new HttpEntity<>(body, headers),
  145 + new ParameterizedTypeReference<CommonResult<Boolean>>() {}); // 解决 CommonResult 的泛型丢失
  146 + Assert.isTrue(exchange.getStatusCode().is2xxSuccessful(), "响应必须是 200 成功");
  147 + return exchange.getBody();
  148 + }
  149 +
124 150 private static void addClientHeader(HttpHeaders headers) {
125 151 // client 拼接,需要 BASE64 编码
126 152 String client = CLIENT_ID + ":" + CLIENT_SECRET;
... ...
yudao-example/yudao-sso-demo-by-code/src/main/java/cn/iocoder/yudao/ssodemo/controller/AuthController.java
1 1 package cn.iocoder.yudao.ssodemo.controller;
2 2  
  3 +import cn.hutool.core.util.StrUtil;
3 4 import cn.iocoder.yudao.ssodemo.client.OAuth2Client;
4 5 import cn.iocoder.yudao.ssodemo.client.dto.CommonResult;
5 6 import cn.iocoder.yudao.ssodemo.client.dto.oauth2.OAuth2AccessTokenRespDTO;
  7 +import cn.iocoder.yudao.ssodemo.framework.core.util.SecurityUtils;
6 8 import org.springframework.web.bind.annotation.PostMapping;
7 9 import org.springframework.web.bind.annotation.RequestMapping;
8 10 import org.springframework.web.bind.annotation.RequestParam;
9 11 import org.springframework.web.bind.annotation.RestController;
10 12  
11 13 import javax.annotation.Resource;
  14 +import javax.servlet.http.HttpServletRequest;
12 15  
13 16 @RestController
14 17 @RequestMapping("/auth")
... ... @@ -41,4 +44,20 @@ public class AuthController {
41 44 return oauth2Client.refreshToken(refreshToken);
42 45 }
43 46  
  47 + /**
  48 + * 退出登录
  49 + *
  50 + * @param request 请求
  51 + * @return 成功
  52 + */
  53 + @PostMapping("/logout")
  54 + public CommonResult<Boolean> logout(HttpServletRequest request) {
  55 + String token = SecurityUtils.obtainAuthorization(request, "Authentication");
  56 + if (StrUtil.isNotBlank(token)) {
  57 + return oauth2Client.revokeToken(token);
  58 + }
  59 + // 返回成功
  60 + return new CommonResult<>();
  61 + }
  62 +
44 63 }
... ...
yudao-example/yudao-sso-demo-by-code/src/main/java/cn/iocoder/yudao/ssodemo/framework/config/SecurityConfiguration.java
... ... @@ -31,6 +31,8 @@ public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
31 31 .antMatchers(HttpMethod.GET, "/*.html", "/**/*.html", "/**/*.css", "/**/*.js").permitAll()
32 32 // 2. 登录相关的接口,可匿名访问
33 33 .antMatchers("/auth/login-by-code").permitAll()
  34 + .antMatchers("/auth/refresh-token").permitAll()
  35 + .antMatchers("/auth/logout").permitAll()
34 36 // last. 兜底规则,必须认证
35 37 .and().authorizeRequests()
36 38 .anyRequest().authenticated();
... ...
yudao-example/yudao-sso-demo-by-code/src/main/resources/static/index.html
... ... @@ -74,6 +74,36 @@
74 74 });
75 75 }
76 76  
  77 + /**
  78 + * 刷新令牌
  79 + */
  80 + function logout() {
  81 + const accessToken = localStorage.getItem('ACCESS-TOKEN');
  82 + if (!accessToken) {
  83 + location.reload();
  84 + return;
  85 + }
  86 + $.ajax({
  87 + url: "http://127.0.0.1:18080/auth/logout",
  88 + method: 'POST',
  89 + headers: {
  90 + 'Authentication': 'Bearer ' + accessToken
  91 + },
  92 + success: function (result) {
  93 + if (result.code !== 0) {
  94 + alert('退出登录失败,原因:' + result.msg)
  95 + return;
  96 + }
  97 + alert('退出登录成功!');
  98 + // 删除 localStorage 中
  99 + localStorage.removeItem('ACCESS-TOKEN');
  100 + localStorage.removeItem('REFRESH-TOKEN');
  101 +
  102 + location.reload();
  103 + }
  104 + });
  105 + }
  106 +
77 107 $(function () {
78 108 const accessToken = localStorage.getItem('ACCESS-TOKEN');
79 109 // 情况一:未登录
... ... @@ -111,7 +141,7 @@
111 141  
112 142 <!-- 情况二:已登录:1)展示用户信息;2)刷新访问令牌;3)退出登录 -->
113 143 <div id="yesLoginDiv" style="display: none">
114   - 您已登录!<button>退出登录</button> <br />
  144 + 您已登录!<button onclick="logout()">退出登录</button> <br />
115 145 昵称:<span id="nicknameSpan"> 加载中... </span> <button onclick="updateNickname()">修改昵称</button> <br />
116 146 访问令牌:<span id="accessTokenSpan"> 加载中... </span> <button onclick="refreshToken()">刷新令牌</button> <br />
117 147 </div>
... ...