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

This commit is contained in:
YunaiV 2022-10-01 21:26:45 +08:00
parent ff54f16907
commit ab40254bc1
4 changed files with 78 additions and 1 deletions

View File

@ -121,6 +121,32 @@ public class OAuth2Client {
return exchange.getBody(); return exchange.getBody();
} }
/**
* 删除访问令牌
*
* @param token 访问令牌
* @return 成功
*/
public CommonResult<Boolean> revokeToken(String token) {
// 1.1 构建请求头
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
headers.set("tenant-id", TENANT_ID.toString());
addClientHeader(headers);
// 1.2 构建请求参数
MultiValueMap<String, Object> body = new LinkedMultiValueMap<>();
body.add("token", token);
// 2. 执行请求
ResponseEntity<CommonResult<Boolean>> exchange = restTemplate.exchange(
BASE_URL + "/token",
HttpMethod.DELETE,
new HttpEntity<>(body, headers),
new ParameterizedTypeReference<CommonResult<Boolean>>() {}); // 解决 CommonResult 的泛型丢失
Assert.isTrue(exchange.getStatusCode().is2xxSuccessful(), "响应必须是 200 成功");
return exchange.getBody();
}
private static void addClientHeader(HttpHeaders headers) { private static void addClientHeader(HttpHeaders headers) {
// client 拼接需要 BASE64 编码 // client 拼接需要 BASE64 编码
String client = CLIENT_ID + ":" + CLIENT_SECRET; String client = CLIENT_ID + ":" + CLIENT_SECRET;

View File

@ -1,14 +1,17 @@
package cn.iocoder.yudao.ssodemo.controller; package cn.iocoder.yudao.ssodemo.controller;
import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.ssodemo.client.OAuth2Client; import cn.iocoder.yudao.ssodemo.client.OAuth2Client;
import cn.iocoder.yudao.ssodemo.client.dto.CommonResult; import cn.iocoder.yudao.ssodemo.client.dto.CommonResult;
import cn.iocoder.yudao.ssodemo.client.dto.oauth2.OAuth2AccessTokenRespDTO; import cn.iocoder.yudao.ssodemo.client.dto.oauth2.OAuth2AccessTokenRespDTO;
import cn.iocoder.yudao.ssodemo.framework.core.util.SecurityUtils;
import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource; import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
@RestController @RestController
@RequestMapping("/auth") @RequestMapping("/auth")
@ -41,4 +44,20 @@ public class AuthController {
return oauth2Client.refreshToken(refreshToken); return oauth2Client.refreshToken(refreshToken);
} }
/**
* 退出登录
*
* @param request 请求
* @return 成功
*/
@PostMapping("/logout")
public CommonResult<Boolean> logout(HttpServletRequest request) {
String token = SecurityUtils.obtainAuthorization(request, "Authentication");
if (StrUtil.isNotBlank(token)) {
return oauth2Client.revokeToken(token);
}
// 返回成功
return new CommonResult<>();
}
} }

View File

@ -31,6 +31,8 @@ public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
.antMatchers(HttpMethod.GET, "/*.html", "/**/*.html", "/**/*.css", "/**/*.js").permitAll() .antMatchers(HttpMethod.GET, "/*.html", "/**/*.html", "/**/*.css", "/**/*.js").permitAll()
// 2. 登录相关的接口可匿名访问 // 2. 登录相关的接口可匿名访问
.antMatchers("/auth/login-by-code").permitAll() .antMatchers("/auth/login-by-code").permitAll()
.antMatchers("/auth/refresh-token").permitAll()
.antMatchers("/auth/logout").permitAll()
// last. 兜底规则必须认证 // last. 兜底规则必须认证
.and().authorizeRequests() .and().authorizeRequests()
.anyRequest().authenticated(); .anyRequest().authenticated();

View File

@ -74,6 +74,36 @@
}); });
} }
/**
* 刷新令牌
*/
function logout() {
const accessToken = localStorage.getItem('ACCESS-TOKEN');
if (!accessToken) {
location.reload();
return;
}
$.ajax({
url: "http://127.0.0.1:18080/auth/logout",
method: 'POST',
headers: {
'Authentication': 'Bearer ' + accessToken
},
success: function (result) {
if (result.code !== 0) {
alert('退出登录失败,原因:' + result.msg)
return;
}
alert('退出登录成功!');
// 删除 localStorage 中
localStorage.removeItem('ACCESS-TOKEN');
localStorage.removeItem('REFRESH-TOKEN');
location.reload();
}
});
}
$(function () { $(function () {
const accessToken = localStorage.getItem('ACCESS-TOKEN'); const accessToken = localStorage.getItem('ACCESS-TOKEN');
// 情况一:未登录 // 情况一:未登录
@ -111,7 +141,7 @@
<!-- 情况二已登录1展示用户信息2刷新访问令牌3退出登录 --> <!-- 情况二已登录1展示用户信息2刷新访问令牌3退出登录 -->
<div id="yesLoginDiv" style="display: none"> <div id="yesLoginDiv" style="display: none">
您已登录!<button>退出登录</button> <br /> 您已登录!<button onclick="logout()">退出登录</button> <br />
昵称:<span id="nicknameSpan"> 加载中... </span> <button onclick="updateNickname()">修改昵称</button> <br /> 昵称:<span id="nicknameSpan"> 加载中... </span> <button onclick="updateNickname()">修改昵称</button> <br />
访问令牌:<span id="accessTokenSpan"> 加载中... </span> <button onclick="refreshToken()">刷新令牌</button> <br /> 访问令牌:<span id="accessTokenSpan"> 加载中... </span> <button onclick="refreshToken()">刷新令牌</button> <br />
</div> </div>