Commit 16b8f3ba9484cb936664c84bfbc6caae42d525f8

Authored by YunaiV
1 parent 1d00261c

【移除】移除 yudao-example 项目,统一到 https://gitee.com/yudaocode/yudao-demo

Showing 44 changed files with 0 additions and 2537 deletions
@@ -23,8 +23,6 @@ @@ -23,8 +23,6 @@
23 <!-- <module>yudao-module-mall</module>--> 23 <!-- <module>yudao-module-mall</module>-->
24 <!-- <module>yudao-module-crm</module>--> 24 <!-- <module>yudao-module-crm</module>-->
25 <!-- <module>yudao-module-erp</module>--> 25 <!-- <module>yudao-module-erp</module>-->
26 - <!-- 示例项目 -->  
27 -<!-- <module>yudao-example</module>-->  
28 </modules> 26 </modules>
29 27
30 <name>${project.artifactId}</name> 28 <name>${project.artifactId}</name>
yudao-example/pom.xml deleted
1 -<?xml version="1.0" encoding="UTF-8"?>  
2 -<project xmlns="http://maven.apache.org/POM/4.0.0"  
3 - xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
4 - xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">  
5 - <modelVersion>4.0.0</modelVersion>  
6 -  
7 - <!-- 由于方便大家拷贝,使用不使用 yudao 作为 Maven parent -->  
8 -  
9 - <groupId>cn.iocoder.boot</groupId>  
10 - <artifactId>yudao-example</artifactId>  
11 - <version>1.0.0-snapshot</version>  
12 - <packaging>pom</packaging>  
13 - <modules>  
14 - <module>yudao-sso-demo-by-code</module>  
15 - <module>yudao-sso-demo-by-password</module>  
16 - </modules>  
17 -  
18 - <name>${project.artifactId}</name>  
19 - <description>提供各种示例,例如说:SSO 单点登录</description>  
20 - <url>https://github.com/YunaiV/ruoyi-vue-pro</url>  
21 -  
22 -</project>  
yudao-example/yudao-sso-demo-by-code/pom.xml deleted
1 -<?xml version="1.0" encoding="UTF-8"?>  
2 -<project xmlns="http://maven.apache.org/POM/4.0.0"  
3 - xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
4 - xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">  
5 - <modelVersion>4.0.0</modelVersion>  
6 -  
7 - <!-- 由于方便大家拷贝,使用不使用 yudao 作为 Maven parent -->  
8 -  
9 - <groupId>cn.iocoder.boot</groupId>  
10 - <artifactId>yudao-sso-demo-by-code</artifactId>  
11 - <version>1.0.0-snapshot</version>  
12 - <packaging>jar</packaging>  
13 -  
14 - <name>${project.artifactId}</name>  
15 - <description>基于授权码模式,如何实现 SSO 单点登录?</description>  
16 - <url>https://github.com/YunaiV/ruoyi-vue-pro</url>  
17 -  
18 - <properties>  
19 - <!-- Maven 相关 -->  
20 - <maven.compiler.source>21</maven.compiler.source>  
21 - <maven.compiler.target>21</maven.compiler.target>  
22 - <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>  
23 - <!-- 统一依赖管理 -->  
24 - <spring.boot.version>3.2.0</spring.boot.version>  
25 - </properties>  
26 -  
27 - <dependencyManagement>  
28 - <dependencies>  
29 - <!-- 统一依赖管理 -->  
30 - <dependency>  
31 - <groupId>org.springframework.boot</groupId>  
32 - <artifactId>spring-boot-dependencies</artifactId>  
33 - <version>${spring.boot.version}</version>  
34 - <type>pom</type>  
35 - <scope>import</scope>  
36 - </dependency>  
37 - </dependencies>  
38 - </dependencyManagement>  
39 -  
40 - <dependencies>  
41 - <!-- Web 相关 -->  
42 - <dependency>  
43 - <groupId>org.springframework.boot</groupId>  
44 - <artifactId>spring-boot-starter-web</artifactId>  
45 - </dependency>  
46 -  
47 - <dependency>  
48 - <groupId>org.springframework.boot</groupId>  
49 - <artifactId>spring-boot-starter-security</artifactId>  
50 - </dependency>  
51 -  
52 - <dependency>  
53 - <groupId>cn.hutool</groupId>  
54 - <artifactId>hutool-all</artifactId>  
55 - <version>5.8.22</version>  
56 - </dependency>  
57 -  
58 - <dependency>  
59 - <groupId>org.projectlombok</groupId>  
60 - <artifactId>lombok</artifactId>  
61 - <optional>true</optional>  
62 - </dependency>  
63 - </dependencies>  
64 -  
65 -</project>  
yudao-example/yudao-sso-demo-by-code/src/main/java/cn/iocoder/yudao/ssodemo/SSODemoApplication.java deleted
1 -package cn.iocoder.yudao.ssodemo;  
2 -  
3 -import org.springframework.boot.SpringApplication;  
4 -import org.springframework.boot.autoconfigure.SpringBootApplication;  
5 -  
6 -@SpringBootApplication  
7 -public class SSODemoApplication {  
8 -  
9 - public static void main(String[] args) {  
10 - SpringApplication.run(SSODemoApplication.class, args);  
11 - }  
12 -  
13 -}  
yudao-example/yudao-sso-demo-by-code/src/main/java/cn/iocoder/yudao/ssodemo/client/OAuth2Client.java deleted
1 -package cn.iocoder.yudao.ssodemo.client;  
2 -  
3 -import cn.iocoder.yudao.ssodemo.client.dto.CommonResult;  
4 -import cn.iocoder.yudao.ssodemo.client.dto.oauth2.OAuth2AccessTokenRespDTO;  
5 -import cn.iocoder.yudao.ssodemo.client.dto.oauth2.OAuth2CheckTokenRespDTO;  
6 -import org.springframework.core.ParameterizedTypeReference;  
7 -import org.springframework.http.*;  
8 -import org.springframework.stereotype.Component;  
9 -import org.springframework.util.Assert;  
10 -import org.springframework.util.Base64Utils;  
11 -import org.springframework.util.LinkedMultiValueMap;  
12 -import org.springframework.util.MultiValueMap;  
13 -import org.springframework.web.client.RestTemplate;  
14 -  
15 -import java.nio.charset.StandardCharsets;  
16 -  
17 -/**  
18 - * OAuth 2.0 客户端  
19 - *  
20 - * 对应调用 OAuth2OpenController 接口  
21 - */  
22 -@Component  
23 -public class OAuth2Client {  
24 -  
25 - private static final String BASE_URL = "http://127.0.0.1:48080/admin-api/system/oauth2";  
26 -  
27 - /**  
28 - * 租户编号  
29 - *  
30 - * 默认使用 1;如果使用别的租户,可以调整  
31 - */  
32 - public static final Long TENANT_ID = 1L;  
33 -  
34 - private static final String CLIENT_ID = "yudao-sso-demo-by-code";  
35 - private static final String CLIENT_SECRET = "test";  
36 -  
37 -  
38 -// @Resource // 可优化,注册一个 RestTemplate Bean,然后注入  
39 - private final RestTemplate restTemplate = new RestTemplate();  
40 -  
41 - /**  
42 - * 使用 code 授权码,获得访问令牌  
43 - *  
44 - * @param code 授权码  
45 - * @param redirectUri 重定向 URI  
46 - * @return 访问令牌  
47 - */  
48 - public CommonResult<OAuth2AccessTokenRespDTO> postAccessToken(String code, String redirectUri) {  
49 - // 1.1 构建请求头  
50 - HttpHeaders headers = new HttpHeaders();  
51 - headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);  
52 - headers.set("tenant-id", TENANT_ID.toString());  
53 - addClientHeader(headers);  
54 - // 1.2 构建请求参数  
55 - MultiValueMap<String, Object> body = new LinkedMultiValueMap<>();  
56 - body.add("grant_type", "authorization_code");  
57 - body.add("code", code);  
58 - body.add("redirect_uri", redirectUri);  
59 -// body.add("state", ""); // 选填;填了会校验  
60 -  
61 - // 2. 执行请求  
62 - ResponseEntity<CommonResult<OAuth2AccessTokenRespDTO>> exchange = restTemplate.exchange(  
63 - BASE_URL + "/token",  
64 - HttpMethod.POST,  
65 - new HttpEntity<>(body, headers),  
66 - new ParameterizedTypeReference<CommonResult<OAuth2AccessTokenRespDTO>>() {}); // 解决 CommonResult 的泛型丢失  
67 - Assert.isTrue(exchange.getStatusCode().is2xxSuccessful(), "响应必须是 200 成功");  
68 - return exchange.getBody();  
69 - }  
70 -  
71 - /**  
72 - * 校验访问令牌,并返回它的基本信息  
73 - *  
74 - * @param token 访问令牌  
75 - * @return 访问令牌的基本信息  
76 - */  
77 - public CommonResult<OAuth2CheckTokenRespDTO> checkToken(String token) {  
78 - // 1.1 构建请求头  
79 - HttpHeaders headers = new HttpHeaders();  
80 - headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);  
81 - headers.set("tenant-id", TENANT_ID.toString());  
82 - addClientHeader(headers);  
83 - // 1.2 构建请求参数  
84 - MultiValueMap<String, Object> body = new LinkedMultiValueMap<>();  
85 - body.add("token", token);  
86 -  
87 - // 2. 执行请求  
88 - ResponseEntity<CommonResult<OAuth2CheckTokenRespDTO>> exchange = restTemplate.exchange(  
89 - BASE_URL + "/check-token",  
90 - HttpMethod.POST,  
91 - new HttpEntity<>(body, headers),  
92 - new ParameterizedTypeReference<CommonResult<OAuth2CheckTokenRespDTO>>() {}); // 解决 CommonResult 的泛型丢失  
93 - Assert.isTrue(exchange.getStatusCode().is2xxSuccessful(), "响应必须是 200 成功");  
94 - return exchange.getBody();  
95 - }  
96 -  
97 - /**  
98 - * 使用刷新令牌,获得(刷新)访问令牌  
99 - *  
100 - * @param refreshToken 刷新令牌  
101 - * @return 访问令牌  
102 - */  
103 - public CommonResult<OAuth2AccessTokenRespDTO> refreshToken(String refreshToken) {  
104 - // 1.1 构建请求头  
105 - HttpHeaders headers = new HttpHeaders();  
106 - headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);  
107 - headers.set("tenant-id", TENANT_ID.toString());  
108 - addClientHeader(headers);  
109 - // 1.2 构建请求参数  
110 - MultiValueMap<String, Object> body = new LinkedMultiValueMap<>();  
111 - body.add("grant_type", "refresh_token");  
112 - body.add("refresh_token", refreshToken);  
113 -  
114 - // 2. 执行请求  
115 - ResponseEntity<CommonResult<OAuth2AccessTokenRespDTO>> exchange = restTemplate.exchange(  
116 - BASE_URL + "/token",  
117 - HttpMethod.POST,  
118 - new HttpEntity<>(body, headers),  
119 - new ParameterizedTypeReference<CommonResult<OAuth2AccessTokenRespDTO>>() {}); // 解决 CommonResult 的泛型丢失  
120 - Assert.isTrue(exchange.getStatusCode().is2xxSuccessful(), "响应必须是 200 成功");  
121 - return exchange.getBody();  
122 - }  
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 -  
150 - private static void addClientHeader(HttpHeaders headers) {  
151 - // client 拼接,需要 BASE64 编码  
152 - String client = CLIENT_ID + ":" + CLIENT_SECRET;  
153 - client = Base64Utils.encodeToString(client.getBytes(StandardCharsets.UTF_8));  
154 - headers.add("Authorization", "Basic " + client);  
155 - }  
156 -  
157 -}  
yudao-example/yudao-sso-demo-by-code/src/main/java/cn/iocoder/yudao/ssodemo/client/UserClient.java deleted
1 -package cn.iocoder.yudao.ssodemo.client;  
2 -  
3 -import cn.iocoder.yudao.ssodemo.client.dto.CommonResult;  
4 -import cn.iocoder.yudao.ssodemo.client.dto.user.UserInfoRespDTO;  
5 -import cn.iocoder.yudao.ssodemo.client.dto.user.UserUpdateReqDTO;  
6 -import cn.iocoder.yudao.ssodemo.framework.core.LoginUser;  
7 -import cn.iocoder.yudao.ssodemo.framework.core.util.SecurityUtils;  
8 -import org.springframework.core.ParameterizedTypeReference;  
9 -import org.springframework.http.*;  
10 -import org.springframework.stereotype.Component;  
11 -import org.springframework.util.Assert;  
12 -import org.springframework.util.LinkedMultiValueMap;  
13 -import org.springframework.util.MultiValueMap;  
14 -import org.springframework.web.client.RestTemplate;  
15 -  
16 -/**  
17 - * 用户 User 信息的客户端  
18 - *  
19 - * 对应调用 OAuth2UserController 接口  
20 - */  
21 -@Component  
22 -public class UserClient {  
23 -  
24 - private static final String BASE_URL = "http://127.0.0.1:48080/admin-api//system/oauth2/user";  
25 -  
26 - // @Resource // 可优化,注册一个 RestTemplate Bean,然后注入  
27 - private final RestTemplate restTemplate = new RestTemplate();  
28 -  
29 - public CommonResult<UserInfoRespDTO> getUser() {  
30 - // 1.1 构建请求头  
31 - HttpHeaders headers = new HttpHeaders();  
32 - headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);  
33 - headers.set("tenant-id", OAuth2Client.TENANT_ID.toString());  
34 - addTokenHeader(headers);  
35 - // 1.2 构建请求参数  
36 - MultiValueMap<String, Object> body = new LinkedMultiValueMap<>();  
37 -  
38 - // 2. 执行请求  
39 - ResponseEntity<CommonResult<UserInfoRespDTO>> exchange = restTemplate.exchange(  
40 - BASE_URL + "/get",  
41 - HttpMethod.GET,  
42 - new HttpEntity<>(body, headers),  
43 - new ParameterizedTypeReference<CommonResult<UserInfoRespDTO>>() {}); // 解决 CommonResult 的泛型丢失  
44 - Assert.isTrue(exchange.getStatusCode().is2xxSuccessful(), "响应必须是 200 成功");  
45 - return exchange.getBody();  
46 - }  
47 -  
48 - public CommonResult<Boolean> updateUser(UserUpdateReqDTO updateReqDTO) {  
49 - // 1.1 构建请求头  
50 - HttpHeaders headers = new HttpHeaders();  
51 - headers.setContentType(MediaType.APPLICATION_JSON);  
52 - headers.set("tenant-id", OAuth2Client.TENANT_ID.toString());  
53 - addTokenHeader(headers);  
54 - // 1.2 构建请求参数  
55 - // 使用 updateReqDTO 即可  
56 -  
57 - // 2. 执行请求  
58 - ResponseEntity<CommonResult<Boolean>> exchange = restTemplate.exchange(  
59 - BASE_URL + "/update",  
60 - HttpMethod.PUT,  
61 - new HttpEntity<>(updateReqDTO, headers),  
62 - new ParameterizedTypeReference<CommonResult<Boolean>>() {}); // 解决 CommonResult 的泛型丢失  
63 - Assert.isTrue(exchange.getStatusCode().is2xxSuccessful(), "响应必须是 200 成功");  
64 - return exchange.getBody();  
65 - }  
66 -  
67 -  
68 - private static void addTokenHeader(HttpHeaders headers) {  
69 - LoginUser loginUser = SecurityUtils.getLoginUser();  
70 - Assert.notNull(loginUser, "登录用户不能为空");  
71 - headers.add("Authorization", "Bearer " + loginUser.getAccessToken());  
72 - }  
73 -}  
yudao-example/yudao-sso-demo-by-code/src/main/java/cn/iocoder/yudao/ssodemo/client/dto/CommonResult.java deleted
1 -package cn.iocoder.yudao.ssodemo.client.dto;  
2 -  
3 -import lombok.Data;  
4 -  
5 -import java.io.Serializable;  
6 -  
7 -/**  
8 - * 通用返回  
9 - *  
10 - * @param <T> 数据泛型  
11 - */  
12 -@Data  
13 -public class CommonResult<T> implements Serializable {  
14 -  
15 - /**  
16 - * 错误码  
17 - */  
18 - private Integer code;  
19 - /**  
20 - * 返回数据  
21 - */  
22 - private T data;  
23 - /**  
24 - * 错误提示,用户可阅读  
25 - */  
26 - private String msg;  
27 -  
28 -}  
yudao-example/yudao-sso-demo-by-code/src/main/java/cn/iocoder/yudao/ssodemo/client/dto/oauth2/OAuth2AccessTokenRespDTO.java deleted
1 -package cn.iocoder.yudao.ssodemo.client.dto.oauth2;  
2 -  
3 -import com.fasterxml.jackson.annotation.JsonProperty;  
4 -import lombok.AllArgsConstructor;  
5 -import lombok.Data;  
6 -import lombok.NoArgsConstructor;  
7 -  
8 -/**  
9 - * 访问令牌 Response DTO  
10 - */  
11 -@Data  
12 -@NoArgsConstructor  
13 -@AllArgsConstructor  
14 -public class OAuth2AccessTokenRespDTO {  
15 -  
16 - /**  
17 - * 访问令牌  
18 - */  
19 - @JsonProperty("access_token")  
20 - private String accessToken;  
21 -  
22 - /**  
23 - * 刷新令牌  
24 - */  
25 - @JsonProperty("refresh_token")  
26 - private String refreshToken;  
27 -  
28 - /**  
29 - * 令牌类型  
30 - */  
31 - @JsonProperty("token_type")  
32 - private String tokenType;  
33 -  
34 - /**  
35 - * 过期时间;单位:秒  
36 - */  
37 - @JsonProperty("expires_in")  
38 - private Long expiresIn;  
39 -  
40 - /**  
41 - * 授权范围;如果多个授权范围,使用空格分隔  
42 - */  
43 - private String scope;  
44 -  
45 -}  
yudao-example/yudao-sso-demo-by-code/src/main/java/cn/iocoder/yudao/ssodemo/client/dto/oauth2/OAuth2CheckTokenRespDTO.java deleted
1 -package cn.iocoder.yudao.ssodemo.client.dto.oauth2;  
2 -  
3 -import com.fasterxml.jackson.annotation.JsonProperty;  
4 -import lombok.AllArgsConstructor;  
5 -import lombok.Data;  
6 -import lombok.NoArgsConstructor;  
7 -  
8 -import java.util.List;  
9 -  
10 -/**  
11 - * 校验令牌 Response DTO  
12 - *  
13 - * @author 芋道源码  
14 - */  
15 -@Data  
16 -@NoArgsConstructor  
17 -@AllArgsConstructor  
18 -public class OAuth2CheckTokenRespDTO {  
19 -  
20 - /**  
21 - * 用户编号  
22 - */  
23 - @JsonProperty("user_id")  
24 - private Long userId;  
25 - /**  
26 - * 用户类型  
27 - */  
28 - @JsonProperty("user_type")  
29 - private Integer userType;  
30 - /**  
31 - * 租户编号  
32 - */  
33 - @JsonProperty("tenant_id")  
34 - private Long tenantId;  
35 -  
36 - /**  
37 - * 客户端编号  
38 - */  
39 - @JsonProperty("client_id")  
40 - private String clientId;  
41 - /**  
42 - * 授权范围  
43 - */  
44 - private List<String> scopes;  
45 -  
46 - /**  
47 - * 访问令牌  
48 - */  
49 - @JsonProperty("access_token")  
50 - private String accessToken;  
51 -  
52 - /**  
53 - * 过期时间  
54 - *  
55 - * 时间戳 / 1000,即单位:秒  
56 - */  
57 - private Long exp;  
58 -  
59 -}  
yudao-example/yudao-sso-demo-by-code/src/main/java/cn/iocoder/yudao/ssodemo/client/dto/user/UserInfoRespDTO.java deleted
1 -package cn.iocoder.yudao.ssodemo.client.dto.user;  
2 -  
3 -import lombok.AllArgsConstructor;  
4 -import lombok.Data;  
5 -import lombok.NoArgsConstructor;  
6 -  
7 -import java.util.List;  
8 -  
9 -/**  
10 - * 获得用户基本信息 Response dto  
11 - */  
12 -@Data  
13 -@NoArgsConstructor  
14 -@AllArgsConstructor  
15 -public class UserInfoRespDTO {  
16 -  
17 - /**  
18 - * 用户编号  
19 - */  
20 - private Long id;  
21 -  
22 - /**  
23 - * 用户账号  
24 - */  
25 - private String username;  
26 -  
27 - /**  
28 - * 用户昵称  
29 - */  
30 - private String nickname;  
31 -  
32 - /**  
33 - * 用户邮箱  
34 - */  
35 - private String email;  
36 - /**  
37 - * 手机号码  
38 - */  
39 - private String mobile;  
40 -  
41 - /**  
42 - * 用户性别  
43 - */  
44 - private Integer sex;  
45 -  
46 - /**  
47 - * 用户头像  
48 - */  
49 - private String avatar;  
50 -  
51 - /**  
52 - * 所在部门  
53 - */  
54 - private Dept dept;  
55 -  
56 - /**  
57 - * 所属岗位数组  
58 - */  
59 - private List<Post> posts;  
60 -  
61 - /**  
62 - * 部门  
63 - */  
64 - @Data  
65 - public static class Dept {  
66 -  
67 - /**  
68 - * 部门编号  
69 - */  
70 - private Long id;  
71 -  
72 - /**  
73 - * 部门名称  
74 - */  
75 - private String name;  
76 -  
77 - }  
78 -  
79 - /**  
80 - * 岗位  
81 - */  
82 - @Data  
83 - public static class Post {  
84 -  
85 - /**  
86 - * 岗位编号  
87 - */  
88 - private Long id;  
89 -  
90 - /**  
91 - * 岗位名称  
92 - */  
93 - private String name;  
94 -  
95 - }  
96 -  
97 -}  
yudao-example/yudao-sso-demo-by-code/src/main/java/cn/iocoder/yudao/ssodemo/client/dto/user/UserUpdateReqDTO.java deleted
1 -package cn.iocoder.yudao.ssodemo.client.dto.user;  
2 -  
3 -import lombok.AllArgsConstructor;  
4 -import lombok.Data;  
5 -import lombok.NoArgsConstructor;  
6 -  
7 -/**  
8 - * 更新用户基本信息 Request DTO  
9 - */  
10 -@Data  
11 -@NoArgsConstructor  
12 -@AllArgsConstructor  
13 -public class UserUpdateReqDTO {  
14 -  
15 - /**  
16 - * 用户昵称  
17 - */  
18 - private String nickname;  
19 -  
20 - /**  
21 - * 用户邮箱  
22 - */  
23 - private String email;  
24 -  
25 - /**  
26 - * 手机号码  
27 - */  
28 - private String mobile;  
29 -  
30 - /**  
31 - * 用户性别  
32 - */  
33 - private Integer sex;  
34 -  
35 -}  
yudao-example/yudao-sso-demo-by-code/src/main/java/cn/iocoder/yudao/ssodemo/controller/AuthController.java deleted
1 -package cn.iocoder.yudao.ssodemo.controller;  
2 -  
3 -import cn.hutool.core.util.StrUtil;  
4 -import cn.iocoder.yudao.ssodemo.client.OAuth2Client;  
5 -import cn.iocoder.yudao.ssodemo.client.dto.CommonResult;  
6 -import cn.iocoder.yudao.ssodemo.client.dto.oauth2.OAuth2AccessTokenRespDTO;  
7 -import cn.iocoder.yudao.ssodemo.framework.core.util.SecurityUtils;  
8 -import org.springframework.web.bind.annotation.PostMapping;  
9 -import org.springframework.web.bind.annotation.RequestMapping;  
10 -import org.springframework.web.bind.annotation.RequestParam;  
11 -import org.springframework.web.bind.annotation.RestController;  
12 -  
13 -import jakarta.annotation.Resource;  
14 -import jakarta.servlet.http.HttpServletRequest;  
15 -  
16 -@RestController  
17 -@RequestMapping("/auth")  
18 -public class AuthController {  
19 -  
20 - @Resource  
21 - private OAuth2Client oauth2Client;  
22 -  
23 - /**  
24 - * 使用 code 访问令牌,获得访问令牌  
25 - *  
26 - * @param code 授权码  
27 - * @param redirectUri 重定向 URI  
28 - * @return 访问令牌;注意,实际项目中,最好创建对应的 ResponseVO 类,只返回必要的字段  
29 - */  
30 - @PostMapping("/login-by-code")  
31 - public CommonResult<OAuth2AccessTokenRespDTO> loginByCode(@RequestParam("code") String code,  
32 - @RequestParam("redirectUri") String redirectUri) {  
33 - return oauth2Client.postAccessToken(code, redirectUri);  
34 - }  
35 -  
36 - /**  
37 - * 使用刷新令牌,获得(刷新)访问令牌  
38 - *  
39 - * @param refreshToken 刷新令牌  
40 - * @return 访问令牌;注意,实际项目中,最好创建对应的 ResponseVO 类,只返回必要的字段  
41 - */  
42 - @PostMapping("/refresh-token")  
43 - public CommonResult<OAuth2AccessTokenRespDTO> refreshToken(@RequestParam("refreshToken") String refreshToken) {  
44 - return oauth2Client.refreshToken(refreshToken);  
45 - }  
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, "Authorization");  
56 - if (StrUtil.isNotBlank(token)) {  
57 - return oauth2Client.revokeToken(token);  
58 - }  
59 - // 返回成功  
60 - return new CommonResult<>();  
61 - }  
62 -  
63 -}  
yudao-example/yudao-sso-demo-by-code/src/main/java/cn/iocoder/yudao/ssodemo/controller/UserController.java deleted
1 -package cn.iocoder.yudao.ssodemo.controller;  
2 -  
3 -import cn.iocoder.yudao.ssodemo.client.UserClient;  
4 -import cn.iocoder.yudao.ssodemo.client.dto.CommonResult;  
5 -import cn.iocoder.yudao.ssodemo.client.dto.user.UserInfoRespDTO;  
6 -import cn.iocoder.yudao.ssodemo.client.dto.user.UserUpdateReqDTO;  
7 -import org.springframework.web.bind.annotation.*;  
8 -  
9 -import jakarta.annotation.Resource;  
10 -  
11 -@RestController  
12 -@RequestMapping("/user")  
13 -public class UserController {  
14 -  
15 - @Resource  
16 - private UserClient userClient;  
17 -  
18 - /**  
19 - * 获得当前登录用户的基本信息  
20 - *  
21 - * @return 用户信息;注意,实际项目中,最好创建对应的 ResponseVO 类,只返回必要的字段  
22 - */  
23 - @GetMapping("/get")  
24 - public CommonResult<UserInfoRespDTO> getUser() {  
25 - return userClient.getUser();  
26 - }  
27 -  
28 - /**  
29 - * 更新当前登录用户的昵称  
30 - *  
31 - * @param nickname 昵称  
32 - * @return 成功  
33 - */  
34 - @PutMapping("/update")  
35 - public CommonResult<Boolean> updateUser(@RequestParam("nickname") String nickname) {  
36 - UserUpdateReqDTO updateReqDTO = new UserUpdateReqDTO(nickname, null, null, null);  
37 - return userClient.updateUser(updateReqDTO);  
38 - }  
39 -  
40 -}  
yudao-example/yudao-sso-demo-by-code/src/main/java/cn/iocoder/yudao/ssodemo/framework/config/SecurityConfiguration.java deleted
1 -package cn.iocoder.yudao.ssodemo.framework.config;  
2 -  
3 -import cn.iocoder.yudao.ssodemo.framework.core.filter.TokenAuthenticationFilter;  
4 -import cn.iocoder.yudao.ssodemo.framework.core.handler.AccessDeniedHandlerImpl;  
5 -import org.springframework.context.annotation.Bean;  
6 -import org.springframework.context.annotation.Configuration;  
7 -import org.springframework.http.HttpMethod;  
8 -import org.springframework.security.config.Customizer;  
9 -import org.springframework.security.config.annotation.web.builders.HttpSecurity;  
10 -import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;  
11 -import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;  
12 -import org.springframework.security.web.AuthenticationEntryPoint;  
13 -import org.springframework.security.web.SecurityFilterChain;  
14 -import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;  
15 -  
16 -import jakarta.annotation.Resource;  
17 -  
18 -@Configuration(proxyBeanMethods = false)  
19 -@EnableWebSecurity  
20 -public class SecurityConfiguration{  
21 -  
22 - @Resource  
23 - private TokenAuthenticationFilter tokenAuthenticationFilter;  
24 -  
25 - @Resource  
26 - private AccessDeniedHandlerImpl accessDeniedHandler;  
27 - @Resource  
28 - private AuthenticationEntryPoint authenticationEntryPoint;  
29 -  
30 - @Bean  
31 - protected SecurityFilterChain filterChain(HttpSecurity httpSecurity) throws Exception {  
32 - // 设置 URL 安全权限  
33 - httpSecurity  
34 - // 开启跨域  
35 - .cors(Customizer.withDefaults())  
36 - // CSRF 禁用,因为不使用 Session  
37 - .csrf(AbstractHttpConfigurer::disable)  
38 - // 一堆自定义的 Spring Security 处理器  
39 - .exceptionHandling(c -> c.authenticationEntryPoint(authenticationEntryPoint)  
40 - .accessDeniedHandler(accessDeniedHandler));  
41 -  
42 - // 设置每个请求的权限  
43 - httpSecurity.authorizeHttpRequests(c -> c  
44 - // 1. 静态资源,可匿名访问  
45 - .requestMatchers(HttpMethod.GET, "/*.html", "/*.html", "/*.css", "/*.js").permitAll()  
46 - // 2. 登录相关的接口,可匿名访问  
47 - .requestMatchers("/auth/login-by-code").permitAll()  
48 - .requestMatchers("/auth/refresh-token").permitAll()  
49 - .requestMatchers("/auth/logout").permitAll())  
50 - // 3. 兜底规则,必须认证  
51 - .authorizeHttpRequests(c -> c.anyRequest().authenticated());  
52 -  
53 - // 添加 Token Filter  
54 - httpSecurity.addFilterBefore(tokenAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);  
55 - return httpSecurity.build();  
56 - }  
57 -  
58 -}  
yudao-example/yudao-sso-demo-by-code/src/main/java/cn/iocoder/yudao/ssodemo/framework/core/LoginUser.java deleted
1 -package cn.iocoder.yudao.ssodemo.framework.core;  
2 -  
3 -import lombok.Data;  
4 -  
5 -import java.util.List;  
6 -  
7 -/**  
8 - * 登录用户信息  
9 - *  
10 - * @author 芋道源码  
11 - */  
12 -@Data  
13 -public class LoginUser {  
14 -  
15 - /**  
16 - * 用户编号  
17 - */  
18 - private Long id;  
19 - /**  
20 - * 用户类型  
21 - */  
22 - private Integer userType;  
23 - /**  
24 - * 租户编号  
25 - */  
26 - private Long tenantId;  
27 - /**  
28 - * 授权范围  
29 - */  
30 - private List<String> scopes;  
31 -  
32 - /**  
33 - * 访问令牌  
34 - */  
35 - private String accessToken;  
36 -  
37 -}  
yudao-example/yudao-sso-demo-by-code/src/main/java/cn/iocoder/yudao/ssodemo/framework/core/filter/TokenAuthenticationFilter.java deleted
1 -package cn.iocoder.yudao.ssodemo.framework.core.filter;  
2 -  
3 -import cn.iocoder.yudao.ssodemo.client.OAuth2Client;  
4 -import cn.iocoder.yudao.ssodemo.client.dto.CommonResult;  
5 -import cn.iocoder.yudao.ssodemo.client.dto.oauth2.OAuth2CheckTokenRespDTO;  
6 -import cn.iocoder.yudao.ssodemo.framework.core.LoginUser;  
7 -import cn.iocoder.yudao.ssodemo.framework.core.util.SecurityUtils;  
8 -import org.springframework.stereotype.Component;  
9 -import org.springframework.util.StringUtils;  
10 -import org.springframework.web.filter.OncePerRequestFilter;  
11 -  
12 -import jakarta.annotation.Resource;  
13 -import jakarta.servlet.FilterChain;  
14 -import jakarta.servlet.ServletException;  
15 -import jakarta.servlet.http.HttpServletRequest;  
16 -import jakarta.servlet.http.HttpServletResponse;  
17 -import java.io.IOException;  
18 -  
19 -/**  
20 - * Token 过滤器,验证 token 的有效性  
21 - * 验证通过后,获得 {@link LoginUser} 信息,并加入到 Spring Security 上下文  
22 - *  
23 - * @author 芋道源码  
24 - */  
25 -@Component  
26 -public class TokenAuthenticationFilter extends OncePerRequestFilter {  
27 -  
28 - @Resource  
29 - private OAuth2Client oauth2Client;  
30 -  
31 - @Override  
32 - protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,  
33 - FilterChain filterChain) throws ServletException, IOException {  
34 - // 1. 获得访问令牌  
35 - String token = SecurityUtils.obtainAuthorization(request, "Authorization");  
36 - if (StringUtils.hasText(token)) {  
37 - // 2. 基于 token 构建登录用户  
38 - LoginUser loginUser = buildLoginUserByToken(token);  
39 - // 3. 设置当前用户  
40 - if (loginUser != null) {  
41 - SecurityUtils.setLoginUser(loginUser, request);  
42 - }  
43 - }  
44 -  
45 - // 继续过滤链  
46 - filterChain.doFilter(request, response);  
47 - }  
48 -  
49 - private LoginUser buildLoginUserByToken(String token) {  
50 - try {  
51 - CommonResult<OAuth2CheckTokenRespDTO> accessTokenResult = oauth2Client.checkToken(token);  
52 - OAuth2CheckTokenRespDTO accessToken = accessTokenResult.getData();  
53 - if (accessToken == null) {  
54 - return null;  
55 - }  
56 - // 构建登录用户  
57 - return new LoginUser().setId(accessToken.getUserId()).setUserType(accessToken.getUserType())  
58 - .setTenantId(accessToken.getTenantId()).setScopes(accessToken.getScopes())  
59 - .setAccessToken(accessToken.getAccessToken());  
60 - } catch (Exception exception) {  
61 - // 校验 Token 不通过时,考虑到一些接口是无需登录的,所以直接返回 null 即可  
62 - return null;  
63 - }  
64 - }  
65 -  
66 -}  
yudao-example/yudao-sso-demo-by-code/src/main/java/cn/iocoder/yudao/ssodemo/framework/core/handler/AccessDeniedHandlerImpl.java deleted
1 -package cn.iocoder.yudao.ssodemo.framework.core.handler;  
2 -  
3 -import cn.iocoder.yudao.ssodemo.client.dto.CommonResult;  
4 -import cn.iocoder.yudao.ssodemo.framework.core.util.SecurityUtils;  
5 -import cn.iocoder.yudao.ssodemo.framework.core.util.ServletUtils;  
6 -import lombok.extern.slf4j.Slf4j;  
7 -import org.springframework.http.HttpStatus;  
8 -import org.springframework.security.access.AccessDeniedException;  
9 -import org.springframework.security.web.access.AccessDeniedHandler;  
10 -import org.springframework.security.web.access.ExceptionTranslationFilter;  
11 -import org.springframework.stereotype.Component;  
12 -  
13 -import jakarta.servlet.FilterChain;  
14 -import jakarta.servlet.ServletException;  
15 -import jakarta.servlet.http.HttpServletRequest;  
16 -import jakarta.servlet.http.HttpServletResponse;  
17 -import java.io.IOException;  
18 -  
19 -/**  
20 - * 访问一个需要认证的 URL 资源,已经认证(登录)但是没有权限的情况下,返回 {@link GlobalErrorCodeConstants#FORBIDDEN} 错误码。  
21 - *  
22 - * 补充:Spring Security 通过 {@link ExceptionTranslationFilter#handleAccessDeniedException(HttpServletRequest, HttpServletResponse, FilterChain, AccessDeniedException)} 方法,调用当前类  
23 - *  
24 - * @author 芋道源码  
25 - */  
26 -@Component  
27 -@SuppressWarnings("JavadocReference")  
28 -@Slf4j  
29 -public class AccessDeniedHandlerImpl implements AccessDeniedHandler {  
30 -  
31 - @Override  
32 - public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException e)  
33 - throws IOException, ServletException {  
34 - // 打印 warn 的原因是,不定期合并 warn,看看有没恶意破坏  
35 - log.warn("[commence][访问 URL({}) 时,用户({}) 权限不够]", request.getRequestURI(),  
36 - SecurityUtils.getLoginUserId(), e);  
37 - // 返回 403  
38 - CommonResult<Object> result = new CommonResult<>();  
39 - result.setCode(HttpStatus.FORBIDDEN.value());  
40 - result.setMsg("没有该操作权限");  
41 - ServletUtils.writeJSON(response, result);  
42 - }  
43 -  
44 -}  
yudao-example/yudao-sso-demo-by-code/src/main/java/cn/iocoder/yudao/ssodemo/framework/core/handler/AuthenticationEntryPointImpl.java deleted
1 -package cn.iocoder.yudao.ssodemo.framework.core.handler;  
2 -  
3 -import cn.iocoder.yudao.ssodemo.client.dto.CommonResult;  
4 -import cn.iocoder.yudao.ssodemo.framework.core.util.ServletUtils;  
5 -import lombok.extern.slf4j.Slf4j;  
6 -import org.springframework.http.HttpStatus;  
7 -import org.springframework.security.core.AuthenticationException;  
8 -import org.springframework.security.web.AuthenticationEntryPoint;  
9 -import org.springframework.security.web.access.ExceptionTranslationFilter;  
10 -import org.springframework.stereotype.Component;  
11 -  
12 -import jakarta.servlet.FilterChain;  
13 -import jakarta.servlet.http.HttpServletRequest;  
14 -import jakarta.servlet.http.HttpServletResponse;  
15 -  
16 -/**  
17 - * 访问一个需要认证的 URL 资源,但是此时自己尚未认证(登录)的情况下,返回 {@link GlobalErrorCodeConstants#UNAUTHORIZED} 错误码,从而使前端重定向到登录页  
18 - *  
19 - * 补充:Spring Security 通过 {@link ExceptionTranslationFilter#sendStartAuthentication(HttpServletRequest, HttpServletResponse, FilterChain, AuthenticationException)} 方法,调用当前类  
20 - */  
21 -@Component  
22 -@Slf4j  
23 -@SuppressWarnings("JavadocReference") // 忽略文档引用报错  
24 -public class AuthenticationEntryPointImpl implements AuthenticationEntryPoint {  
25 -  
26 - @Override  
27 - public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException e) {  
28 - log.debug("[commence][访问 URL({}) 时,没有登录]", request.getRequestURI(), e);  
29 - // 返回 401  
30 - CommonResult<Object> result = new CommonResult<>();  
31 - result.setCode(HttpStatus.UNAUTHORIZED.value());  
32 - result.setMsg("账号未登录");  
33 - ServletUtils.writeJSON(response, result);  
34 - }  
35 -  
36 -}  
yudao-example/yudao-sso-demo-by-code/src/main/java/cn/iocoder/yudao/ssodemo/framework/core/util/SecurityUtils.java deleted
1 -package cn.iocoder.yudao.ssodemo.framework.core.util;  
2 -  
3 -import cn.iocoder.yudao.ssodemo.framework.core.LoginUser;  
4 -import org.springframework.lang.Nullable;  
5 -import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;  
6 -import org.springframework.security.core.Authentication;  
7 -import org.springframework.security.core.context.SecurityContext;  
8 -import org.springframework.security.core.context.SecurityContextHolder;  
9 -import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;  
10 -import org.springframework.util.StringUtils;  
11 -  
12 -import jakarta.servlet.http.HttpServletRequest;  
13 -import java.util.Collections;  
14 -  
15 -/**  
16 - * 安全服务工具类  
17 - *  
18 - * @author 芋道源码  
19 - */  
20 -public class SecurityUtils {  
21 -  
22 - public static final String AUTHORIZATION_BEARER = "Bearer";  
23 -  
24 - private SecurityUtils() {}  
25 -  
26 - /**  
27 - * 从请求中,获得认证 Token  
28 - *  
29 - * @param request 请求  
30 - * @param header 认证 Token 对应的 Header 名字  
31 - * @return 认证 Token  
32 - */  
33 - public static String obtainAuthorization(HttpServletRequest request, String header) {  
34 - String authorization = request.getHeader(header);  
35 - if (!StringUtils.hasText(authorization)) {  
36 - return null;  
37 - }  
38 - int index = authorization.indexOf(AUTHORIZATION_BEARER + " ");  
39 - if (index == -1) { // 未找到  
40 - return null;  
41 - }  
42 - return authorization.substring(index + 7).trim();  
43 - }  
44 -  
45 - /**  
46 - * 获得当前认证信息  
47 - *  
48 - * @return 认证信息  
49 - */  
50 - public static Authentication getAuthentication() {  
51 - SecurityContext context = SecurityContextHolder.getContext();  
52 - if (context == null) {  
53 - return null;  
54 - }  
55 - return context.getAuthentication();  
56 - }  
57 -  
58 - /**  
59 - * 获取当前用户  
60 - *  
61 - * @return 当前用户  
62 - */  
63 - @Nullable  
64 - public static LoginUser getLoginUser() {  
65 - Authentication authentication = getAuthentication();  
66 - if (authentication == null) {  
67 - return null;  
68 - }  
69 - return authentication.getPrincipal() instanceof LoginUser ? (LoginUser) authentication.getPrincipal() : null;  
70 - }  
71 -  
72 - /**  
73 - * 获得当前用户的编号,从上下文中  
74 - *  
75 - * @return 用户编号  
76 - */  
77 - @Nullable  
78 - public static Long getLoginUserId() {  
79 - LoginUser loginUser = getLoginUser();  
80 - return loginUser != null ? loginUser.getId() : null;  
81 - }  
82 -  
83 - /**  
84 - * 设置当前用户  
85 - *  
86 - * @param loginUser 登录用户  
87 - * @param request 请求  
88 - */  
89 - public static void setLoginUser(LoginUser loginUser, HttpServletRequest request) {  
90 - // 创建 Authentication,并设置到上下文  
91 - Authentication authentication = buildAuthentication(loginUser, request);  
92 - SecurityContextHolder.getContext().setAuthentication(authentication);  
93 - }  
94 -  
95 - private static Authentication buildAuthentication(LoginUser loginUser, HttpServletRequest request) {  
96 - // 创建 UsernamePasswordAuthenticationToken 对象  
97 - UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(  
98 - loginUser, null, Collections.emptyList());  
99 - authenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));  
100 - return authenticationToken;  
101 - }  
102 -  
103 -}  
yudao-example/yudao-sso-demo-by-code/src/main/java/cn/iocoder/yudao/ssodemo/framework/core/util/ServletUtils.java deleted
1 -package cn.iocoder.yudao.ssodemo.framework.core.util;  
2 -  
3 -import cn.hutool.extra.servlet.JakartaServletUtil;  
4 -import cn.hutool.extra.servlet.ServletUtil;  
5 -import cn.hutool.json.JSONUtil;  
6 -import org.springframework.http.MediaType;  
7 -  
8 -import jakarta.servlet.http.HttpServletResponse;  
9 -  
10 -/**  
11 - * 客户端工具类  
12 - *  
13 - * @author 芋道源码  
14 - */  
15 -public class ServletUtils {  
16 -  
17 - /**  
18 - * 返回 JSON 字符串  
19 - *  
20 - * @param response 响应  
21 - * @param object 对象,会序列化成 JSON 字符串  
22 - */  
23 - @SuppressWarnings("deprecation") // 必须使用 APPLICATION_JSON_UTF8_VALUE,否则会乱码  
24 - public static void writeJSON(HttpServletResponse response, Object object) {  
25 - String content = JSONUtil.toJsonStr(object);  
26 - JakartaServletUtil.write(response, content, MediaType.APPLICATION_JSON_UTF8_VALUE);  
27 - }  
28 -  
29 - public static void write(HttpServletResponse response, String text, String contentType) {  
30 - JakartaServletUtil.write(response, text, contentType);  
31 - }  
32 -  
33 -}  
yudao-example/yudao-sso-demo-by-code/src/main/resources/application.yaml deleted
1 -server:  
2 - port: 18080  
yudao-example/yudao-sso-demo-by-code/src/main/resources/static/callback.html deleted
1 -<!DOCTYPE html>  
2 -<html lang="en">  
3 -<head>  
4 - <meta charset="UTF-8">  
5 - <title>SSO 授权后的回调页</title>  
6 - <!-- jQuery:操作 dom、发起请求等 -->  
7 - <script src="https://lf9-cdn-tos.bytecdntp.com/cdn/expire-1-M/jquery/2.1.2/jquery.min.js" type="application/javascript"></script>  
8 - <!-- 工具类 -->  
9 - <script type="application/javascript">  
10 - (function ($) {  
11 - /**  
12 - * 获得 URL 的指定参数的值  
13 - *  
14 - * @param name 参数名  
15 - * @returns 参数值  
16 - */  
17 - $.getUrlParam = function (name) {  
18 - const reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)");  
19 - const r = window.location.search.substr(1).match(reg);  
20 - if (r != null) return unescape(r[2]); return null;  
21 - }  
22 - })(jQuery);  
23 - </script>  
24 -  
25 - <script type="application/javascript">  
26 - $(function () {  
27 - // 获得 code 授权码  
28 - const code = $.getUrlParam('code');  
29 - if (!code) {  
30 - alert('获取不到 code 参数,请排查!')  
31 - return;  
32 - }  
33 -  
34 - // 提交  
35 - const redirectUri = 'http://127.0.0.1:18080/callback.html'; // 需要修改成,你回调的地址,就是在 index.html 拼接的 redirectUri  
36 - $.ajax({  
37 - url: "http://127.0.0.1:18080/auth/login-by-code?code=" + code  
38 - + '&redirectUri=' + redirectUri,  
39 - method: 'POST',  
40 - success: function( result ) {  
41 - if (result.code !== 0) {  
42 - alert('获得访问令牌失败,原因:' + result.msg)  
43 - return;  
44 - }  
45 - alert('获得访问令牌成功!点击确认,跳转回首页')  
46 -  
47 - // 设置到 localStorage 中  
48 - localStorage.setItem('ACCESS-TOKEN', result.data.access_token);  
49 - localStorage.setItem('REFRESH-TOKEN', result.data.refresh_token);  
50 -  
51 - // 跳转回首页  
52 - window.location.href = '/index.html';  
53 - }  
54 - })  
55 - })  
56 - </script>  
57 -</head>  
58 -<body>  
59 -正在使用 code 授权码,进行 accessToken 访问令牌的获取  
60 -</body>  
61 -</html>  
yudao-example/yudao-sso-demo-by-code/src/main/resources/static/index.html deleted
1 -<!DOCTYPE html>  
2 -<html lang="en">  
3 -<head>  
4 - <meta charset="UTF-8">  
5 - <title>首页</title>  
6 - <!-- jQuery:操作 dom、发起请求等 -->  
7 - <script src="https://lf9-cdn-tos.bytecdntp.com/cdn/expire-1-M/jquery/2.1.2/jquery.min.js" type="application/javascript"></script>  
8 -  
9 - <script type="application/javascript">  
10 -  
11 - /**  
12 - * 跳转单点登录  
13 - */  
14 - function ssoLogin() {  
15 - const clientId = 'yudao-sso-demo-by-code'; // 可以改写成,你的 clientId  
16 - const redirectUri = encodeURIComponent('http://127.0.0.1:18080/callback.html'); // 注意,需要使用 encodeURIComponent 编码地址  
17 - const responseType = 'code'; // 1)授权码模式,对应 code;2)简化模式,对应 token  
18 - window.location.href = 'http://127.0.0.1:1024/sso?client_id=' + clientId  
19 - + '&redirect_uri=' + redirectUri  
20 - + '&response_type=' + responseType;  
21 - }  
22 -  
23 - /**  
24 - * 修改昵称  
25 - */  
26 - function updateNickname() {  
27 - const nickname = prompt("请输入新的昵称", "");  
28 - if (!nickname) {  
29 - return;  
30 - }  
31 - // 更新用户的昵称  
32 - const accessToken = localStorage.getItem('ACCESS-TOKEN');  
33 - $.ajax({  
34 - url: "http://127.0.0.1:18080/user/update?nickname=" + nickname,  
35 - method: 'PUT',  
36 - headers: {  
37 - 'Authorization': 'Bearer ' + accessToken  
38 - },  
39 - success: function (result) {  
40 - if (result.code !== 0) {  
41 - alert('更新昵称失败,原因:' + result.msg)  
42 - return;  
43 - }  
44 - alert('更新昵称成功!');  
45 - $('#nicknameSpan').html(nickname);  
46 - }  
47 - });  
48 - }  
49 -  
50 - /**  
51 - * 刷新令牌  
52 - */  
53 - function refreshToken() {  
54 - const refreshToken = localStorage.getItem('REFRESH-TOKEN');  
55 - if (!refreshToken) {  
56 - alert("获取不到刷新令牌");  
57 - return;  
58 - }  
59 - $.ajax({  
60 - url: "http://127.0.0.1:18080/auth/refresh-token?refreshToken=" + refreshToken,  
61 - method: 'POST',  
62 - success: function (result) {  
63 - if (result.code !== 0) {  
64 - alert('刷新访问令牌失败,原因:' + result.msg)  
65 - return;  
66 - }  
67 - alert('更新访问令牌成功!');  
68 - $('#accessTokenSpan').html(result.data.access_token);  
69 -  
70 - // 设置到 localStorage 中  
71 - localStorage.setItem('ACCESS-TOKEN', result.data.access_token);  
72 - localStorage.setItem('REFRESH-TOKEN', result.data.refresh_token);  
73 - }  
74 - });  
75 - }  
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 - 'Authorization': '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 -  
107 - $(function () {  
108 - const accessToken = localStorage.getItem('ACCESS-TOKEN');  
109 - // 情况一:未登录  
110 - if (!accessToken) {  
111 - $('#noLoginDiv').css("display", "block");  
112 - return;  
113 - }  
114 -  
115 - // 情况二:已登录  
116 - $('#yesLoginDiv').css("display", "block");  
117 - $('#accessTokenSpan').html(accessToken);  
118 - // 获得登录用户的信息  
119 - $.ajax({  
120 - url: "http://127.0.0.1:18080/user/get",  
121 - method: 'GET',  
122 - headers: {  
123 - 'Authorization': 'Bearer ' + accessToken  
124 - },  
125 - success: function (result) {  
126 - if (result.code !== 0) {  
127 - alert('获得个人信息失败,原因:' + result.msg)  
128 - return;  
129 - }  
130 - $('#nicknameSpan').html(result.data.nickname);  
131 - }  
132 - });  
133 - })  
134 - </script>  
135 -</head>  
136 -<body>  
137 -<!-- 情况一:未登录:1)跳转 ruoyi-vue-pro 的 SSO 登录页 -->  
138 -<div id="noLoginDiv" style="display: none">  
139 - 您未登录,点击 <a href="#" onclick="ssoLogin()">跳转 </a> SSO 单点登录  
140 -</div>  
141 -  
142 -<!-- 情况二:已登录:1)展示用户信息;2)刷新访问令牌;3)退出登录 -->  
143 -<div id="yesLoginDiv" style="display: none">  
144 - 您已登录!<button onclick="logout()">退出登录</button> <br />  
145 - 昵称:<span id="nicknameSpan"> 加载中... </span> <button onclick="updateNickname()">修改昵称</button> <br />  
146 - 访问令牌:<span id="accessTokenSpan"> 加载中... </span> <button onclick="refreshToken()">刷新令牌</button> <br />  
147 -</div>  
148 -</body>  
149 -<style>  
150 - body { /** 页面居中 */  
151 - border-radius: 20px;  
152 - height: 350px;  
153 - position: absolute;  
154 - left: 50%;  
155 - top: 50%;  
156 - transform: translate(-50%,-50%);  
157 - }  
158 -</style>  
159 -</html>  
yudao-example/yudao-sso-demo-by-password/pom.xml deleted
1 -<?xml version="1.0" encoding="UTF-8"?>  
2 -<project xmlns="http://maven.apache.org/POM/4.0.0"  
3 - xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
4 - xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">  
5 - <modelVersion>4.0.0</modelVersion>  
6 -  
7 - <!-- 由于方便大家拷贝,使用不使用 yudao 作为 Maven parent -->  
8 -  
9 - <groupId>cn.iocoder.boot</groupId>  
10 - <artifactId>yudao-sso-demo-by-password</artifactId>  
11 - <version>1.0.0-snapshot</version>  
12 - <packaging>jar</packaging>  
13 -  
14 - <name>${project.artifactId}</name>  
15 - <description>基于密码模式,如何实现 SSO 单点登录?</description>  
16 - <url>https://github.com/YunaiV/ruoyi-vue-pro</url>  
17 -  
18 - <properties>  
19 - <!-- Maven 相关 -->  
20 - <maven.compiler.source>21</maven.compiler.source>  
21 - <maven.compiler.target>21</maven.compiler.target>  
22 - <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>  
23 - <!-- 统一依赖管理 -->  
24 - <spring.boot.version>3.2.0</spring.boot.version>  
25 - </properties>  
26 -  
27 - <dependencyManagement>  
28 - <dependencies>  
29 - <!-- 统一依赖管理 -->  
30 - <dependency>  
31 - <groupId>org.springframework.boot</groupId>  
32 - <artifactId>spring-boot-dependencies</artifactId>  
33 - <version>${spring.boot.version}</version>  
34 - <type>pom</type>  
35 - <scope>import</scope>  
36 - </dependency>  
37 - </dependencies>  
38 - </dependencyManagement>  
39 -  
40 - <dependencies>  
41 - <!-- Web 相关 -->  
42 - <dependency>  
43 - <groupId>org.springframework.boot</groupId>  
44 - <artifactId>spring-boot-starter-web</artifactId>  
45 - </dependency>  
46 -  
47 - <dependency>  
48 - <groupId>org.springframework.boot</groupId>  
49 - <artifactId>spring-boot-starter-security</artifactId>  
50 - </dependency>  
51 -  
52 - <dependency>  
53 - <groupId>cn.hutool</groupId>  
54 - <artifactId>hutool-all</artifactId>  
55 - <version>5.8.22</version>  
56 - </dependency>  
57 -  
58 - <dependency>  
59 - <groupId>org.projectlombok</groupId>  
60 - <artifactId>lombok</artifactId>  
61 - <optional>true</optional>  
62 - </dependency>  
63 - </dependencies>  
64 -  
65 -</project>  
yudao-example/yudao-sso-demo-by-password/src/main/java/cn/iocoder/yudao/ssodemo/SSODemoApplication.java deleted
1 -package cn.iocoder.yudao.ssodemo;  
2 -  
3 -import org.springframework.boot.SpringApplication;  
4 -import org.springframework.boot.autoconfigure.SpringBootApplication;  
5 -  
6 -@SpringBootApplication  
7 -public class SSODemoApplication {  
8 -  
9 - public static void main(String[] args) {  
10 - SpringApplication.run(SSODemoApplication.class, args);  
11 - }  
12 -  
13 -}  
yudao-example/yudao-sso-demo-by-password/src/main/java/cn/iocoder/yudao/ssodemo/client/OAuth2Client.java deleted
1 -package cn.iocoder.yudao.ssodemo.client;  
2 -  
3 -import cn.iocoder.yudao.ssodemo.client.dto.CommonResult;  
4 -import cn.iocoder.yudao.ssodemo.client.dto.oauth2.OAuth2AccessTokenRespDTO;  
5 -import cn.iocoder.yudao.ssodemo.client.dto.oauth2.OAuth2CheckTokenRespDTO;  
6 -import org.springframework.core.ParameterizedTypeReference;  
7 -import org.springframework.http.*;  
8 -import org.springframework.stereotype.Component;  
9 -import org.springframework.util.Assert;  
10 -import org.springframework.util.Base64Utils;  
11 -import org.springframework.util.LinkedMultiValueMap;  
12 -import org.springframework.util.MultiValueMap;  
13 -import org.springframework.web.client.RestTemplate;  
14 -  
15 -import java.nio.charset.StandardCharsets;  
16 -  
17 -/**  
18 - * OAuth 2.0 客户端  
19 - *  
20 - * 对应调用 OAuth2OpenController 接口  
21 - */  
22 -@Component  
23 -public class OAuth2Client {  
24 -  
25 - private static final String BASE_URL = "http://127.0.0.1:48080/admin-api/system/oauth2";  
26 -  
27 - /**  
28 - * 租户编号  
29 - *  
30 - * 默认使用 1;如果使用别的租户,可以调整  
31 - */  
32 - public static final Long TENANT_ID = 1L;  
33 -  
34 - private static final String CLIENT_ID = "yudao-sso-demo-by-password";  
35 - private static final String CLIENT_SECRET = "test";  
36 -  
37 -  
38 -// @Resource // 可优化,注册一个 RestTemplate Bean,然后注入  
39 - private final RestTemplate restTemplate = new RestTemplate();  
40 -  
41 - /**  
42 - * 校验访问令牌,并返回它的基本信息  
43 - *  
44 - * @param token 访问令牌  
45 - * @return 访问令牌的基本信息  
46 - */  
47 - public CommonResult<OAuth2CheckTokenRespDTO> checkToken(String token) {  
48 - // 1.1 构建请求头  
49 - HttpHeaders headers = new HttpHeaders();  
50 - headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);  
51 - headers.set("tenant-id", TENANT_ID.toString());  
52 - addClientHeader(headers);  
53 - // 1.2 构建请求参数  
54 - MultiValueMap<String, Object> body = new LinkedMultiValueMap<>();  
55 - body.add("token", token);  
56 -  
57 - // 2. 执行请求  
58 - ResponseEntity<CommonResult<OAuth2CheckTokenRespDTO>> exchange = restTemplate.exchange(  
59 - BASE_URL + "/check-token",  
60 - HttpMethod.POST,  
61 - new HttpEntity<>(body, headers),  
62 - new ParameterizedTypeReference<CommonResult<OAuth2CheckTokenRespDTO>>() {}); // 解决 CommonResult 的泛型丢失  
63 - Assert.isTrue(exchange.getStatusCode().is2xxSuccessful(), "响应必须是 200 成功");  
64 - return exchange.getBody();  
65 - }  
66 -  
67 - /**  
68 - * 使用刷新令牌,获得(刷新)访问令牌  
69 - *  
70 - * @param refreshToken 刷新令牌  
71 - * @return 访问令牌  
72 - */  
73 - public CommonResult<OAuth2AccessTokenRespDTO> refreshToken(String refreshToken) {  
74 - // 1.1 构建请求头  
75 - HttpHeaders headers = new HttpHeaders();  
76 - headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);  
77 - headers.set("tenant-id", TENANT_ID.toString());  
78 - addClientHeader(headers);  
79 - // 1.2 构建请求参数  
80 - MultiValueMap<String, Object> body = new LinkedMultiValueMap<>();  
81 - body.add("grant_type", "refresh_token");  
82 - body.add("refresh_token", refreshToken);  
83 -  
84 - // 2. 执行请求  
85 - ResponseEntity<CommonResult<OAuth2AccessTokenRespDTO>> exchange = restTemplate.exchange(  
86 - BASE_URL + "/token",  
87 - HttpMethod.POST,  
88 - new HttpEntity<>(body, headers),  
89 - new ParameterizedTypeReference<CommonResult<OAuth2AccessTokenRespDTO>>() {}); // 解决 CommonResult 的泛型丢失  
90 - Assert.isTrue(exchange.getStatusCode().is2xxSuccessful(), "响应必须是 200 成功");  
91 - return exchange.getBody();  
92 - }  
93 -  
94 - /**  
95 - * 删除访问令牌  
96 - *  
97 - * @param token 访问令牌  
98 - * @return 成功  
99 - */  
100 - public CommonResult<Boolean> revokeToken(String token) {  
101 - // 1.1 构建请求头  
102 - HttpHeaders headers = new HttpHeaders();  
103 - headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);  
104 - headers.set("tenant-id", TENANT_ID.toString());  
105 - addClientHeader(headers);  
106 - // 1.2 构建请求参数  
107 - MultiValueMap<String, Object> body = new LinkedMultiValueMap<>();  
108 - body.add("token", token);  
109 -  
110 - // 2. 执行请求  
111 - ResponseEntity<CommonResult<Boolean>> exchange = restTemplate.exchange(  
112 - BASE_URL + "/token",  
113 - HttpMethod.DELETE,  
114 - new HttpEntity<>(body, headers),  
115 - new ParameterizedTypeReference<CommonResult<Boolean>>() {}); // 解决 CommonResult 的泛型丢失  
116 - Assert.isTrue(exchange.getStatusCode().is2xxSuccessful(), "响应必须是 200 成功");  
117 - return exchange.getBody();  
118 - }  
119 -  
120 - private static void addClientHeader(HttpHeaders headers) {  
121 - // client 拼接,需要 BASE64 编码  
122 - String client = CLIENT_ID + ":" + CLIENT_SECRET;  
123 - client = Base64Utils.encodeToString(client.getBytes(StandardCharsets.UTF_8));  
124 - headers.add("Authorization", "Basic " + client);  
125 - }  
126 -  
127 -}  
yudao-example/yudao-sso-demo-by-password/src/main/java/cn/iocoder/yudao/ssodemo/client/UserClient.java deleted
1 -package cn.iocoder.yudao.ssodemo.client;  
2 -  
3 -import cn.iocoder.yudao.ssodemo.client.dto.CommonResult;  
4 -import cn.iocoder.yudao.ssodemo.client.dto.user.UserInfoRespDTO;  
5 -import cn.iocoder.yudao.ssodemo.client.dto.user.UserUpdateReqDTO;  
6 -import cn.iocoder.yudao.ssodemo.framework.core.LoginUser;  
7 -import cn.iocoder.yudao.ssodemo.framework.core.util.SecurityUtils;  
8 -import org.springframework.core.ParameterizedTypeReference;  
9 -import org.springframework.http.*;  
10 -import org.springframework.stereotype.Component;  
11 -import org.springframework.util.Assert;  
12 -import org.springframework.util.LinkedMultiValueMap;  
13 -import org.springframework.util.MultiValueMap;  
14 -import org.springframework.web.client.RestTemplate;  
15 -  
16 -/**  
17 - * 用户 User 信息的客户端  
18 - *  
19 - * 对应调用 OAuth2UserController 接口  
20 - */  
21 -@Component  
22 -public class UserClient {  
23 -  
24 - private static final String BASE_URL = "http://127.0.0.1:48080/admin-api//system/oauth2/user";  
25 -  
26 - // @Resource // 可优化,注册一个 RestTemplate Bean,然后注入  
27 - private final RestTemplate restTemplate = new RestTemplate();  
28 -  
29 - public CommonResult<UserInfoRespDTO> getUser() {  
30 - // 1.1 构建请求头  
31 - HttpHeaders headers = new HttpHeaders();  
32 - headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);  
33 - headers.set("tenant-id", OAuth2Client.TENANT_ID.toString());  
34 - addTokenHeader(headers);  
35 - // 1.2 构建请求参数  
36 - MultiValueMap<String, Object> body = new LinkedMultiValueMap<>();  
37 -  
38 - // 2. 执行请求  
39 - ResponseEntity<CommonResult<UserInfoRespDTO>> exchange = restTemplate.exchange(  
40 - BASE_URL + "/get",  
41 - HttpMethod.GET,  
42 - new HttpEntity<>(body, headers),  
43 - new ParameterizedTypeReference<CommonResult<UserInfoRespDTO>>() {}); // 解决 CommonResult 的泛型丢失  
44 - Assert.isTrue(exchange.getStatusCode().is2xxSuccessful(), "响应必须是 200 成功");  
45 - return exchange.getBody();  
46 - }  
47 -  
48 - public CommonResult<Boolean> updateUser(UserUpdateReqDTO updateReqDTO) {  
49 - // 1.1 构建请求头  
50 - HttpHeaders headers = new HttpHeaders();  
51 - headers.setContentType(MediaType.APPLICATION_JSON);  
52 - headers.set("tenant-id", OAuth2Client.TENANT_ID.toString());  
53 - addTokenHeader(headers);  
54 - // 1.2 构建请求参数  
55 - // 使用 updateReqDTO 即可  
56 -  
57 - // 2. 执行请求  
58 - ResponseEntity<CommonResult<Boolean>> exchange = restTemplate.exchange(  
59 - BASE_URL + "/update",  
60 - HttpMethod.PUT,  
61 - new HttpEntity<>(updateReqDTO, headers),  
62 - new ParameterizedTypeReference<CommonResult<Boolean>>() {}); // 解决 CommonResult 的泛型丢失  
63 - Assert.isTrue(exchange.getStatusCode().is2xxSuccessful(), "响应必须是 200 成功");  
64 - return exchange.getBody();  
65 - }  
66 -  
67 -  
68 - private static void addTokenHeader(HttpHeaders headers) {  
69 - LoginUser loginUser = SecurityUtils.getLoginUser();  
70 - Assert.notNull(loginUser, "登录用户不能为空");  
71 - headers.add("Authorization", "Bearer " + loginUser.getAccessToken());  
72 - }  
73 -}  
yudao-example/yudao-sso-demo-by-password/src/main/java/cn/iocoder/yudao/ssodemo/client/dto/CommonResult.java deleted
1 -package cn.iocoder.yudao.ssodemo.client.dto;  
2 -  
3 -import lombok.Data;  
4 -  
5 -import java.io.Serializable;  
6 -  
7 -/**  
8 - * 通用返回  
9 - *  
10 - * @param <T> 数据泛型  
11 - */  
12 -@Data  
13 -public class CommonResult<T> implements Serializable {  
14 -  
15 - /**  
16 - * 错误码  
17 - */  
18 - private Integer code;  
19 - /**  
20 - * 返回数据  
21 - */  
22 - private T data;  
23 - /**  
24 - * 错误提示,用户可阅读  
25 - */  
26 - private String msg;  
27 -  
28 -}  
yudao-example/yudao-sso-demo-by-password/src/main/java/cn/iocoder/yudao/ssodemo/client/dto/oauth2/OAuth2AccessTokenRespDTO.java deleted
1 -package cn.iocoder.yudao.ssodemo.client.dto.oauth2;  
2 -  
3 -import com.fasterxml.jackson.annotation.JsonProperty;  
4 -import lombok.AllArgsConstructor;  
5 -import lombok.Data;  
6 -import lombok.NoArgsConstructor;  
7 -  
8 -/**  
9 - * 访问令牌 Response DTO  
10 - */  
11 -@Data  
12 -@NoArgsConstructor  
13 -@AllArgsConstructor  
14 -public class OAuth2AccessTokenRespDTO {  
15 -  
16 - /**  
17 - * 访问令牌  
18 - */  
19 - @JsonProperty("access_token")  
20 - private String accessToken;  
21 -  
22 - /**  
23 - * 刷新令牌  
24 - */  
25 - @JsonProperty("refresh_token")  
26 - private String refreshToken;  
27 -  
28 - /**  
29 - * 令牌类型  
30 - */  
31 - @JsonProperty("token_type")  
32 - private String tokenType;  
33 -  
34 - /**  
35 - * 过期时间;单位:秒  
36 - */  
37 - @JsonProperty("expires_in")  
38 - private Long expiresIn;  
39 -  
40 - /**  
41 - * 授权范围;如果多个授权范围,使用空格分隔  
42 - */  
43 - private String scope;  
44 -  
45 -}  
yudao-example/yudao-sso-demo-by-password/src/main/java/cn/iocoder/yudao/ssodemo/client/dto/oauth2/OAuth2CheckTokenRespDTO.java deleted
1 -package cn.iocoder.yudao.ssodemo.client.dto.oauth2;  
2 -  
3 -import com.fasterxml.jackson.annotation.JsonProperty;  
4 -import lombok.AllArgsConstructor;  
5 -import lombok.Data;  
6 -import lombok.NoArgsConstructor;  
7 -  
8 -import java.util.List;  
9 -  
10 -/**  
11 - * 校验令牌 Response DTO  
12 - *  
13 - * @author 芋道源码  
14 - */  
15 -@Data  
16 -@NoArgsConstructor  
17 -@AllArgsConstructor  
18 -public class OAuth2CheckTokenRespDTO {  
19 -  
20 - /**  
21 - * 用户编号  
22 - */  
23 - @JsonProperty("user_id")  
24 - private Long userId;  
25 - /**  
26 - * 用户类型  
27 - */  
28 - @JsonProperty("user_type")  
29 - private Integer userType;  
30 - /**  
31 - * 租户编号  
32 - */  
33 - @JsonProperty("tenant_id")  
34 - private Long tenantId;  
35 -  
36 - /**  
37 - * 客户端编号  
38 - */  
39 - @JsonProperty("client_id")  
40 - private String clientId;  
41 - /**  
42 - * 授权范围  
43 - */  
44 - private List<String> scopes;  
45 -  
46 - /**  
47 - * 访问令牌  
48 - */  
49 - @JsonProperty("access_token")  
50 - private String accessToken;  
51 -  
52 - /**  
53 - * 过期时间  
54 - *  
55 - * 时间戳 / 1000,即单位:秒  
56 - */  
57 - private Long exp;  
58 -  
59 -}  
yudao-example/yudao-sso-demo-by-password/src/main/java/cn/iocoder/yudao/ssodemo/client/dto/user/UserInfoRespDTO.java deleted
1 -package cn.iocoder.yudao.ssodemo.client.dto.user;  
2 -  
3 -import lombok.AllArgsConstructor;  
4 -import lombok.Data;  
5 -import lombok.NoArgsConstructor;  
6 -  
7 -import java.util.List;  
8 -  
9 -/**  
10 - * 获得用户基本信息 Response dto  
11 - */  
12 -@Data  
13 -@NoArgsConstructor  
14 -@AllArgsConstructor  
15 -public class UserInfoRespDTO {  
16 -  
17 - /**  
18 - * 用户编号  
19 - */  
20 - private Long id;  
21 -  
22 - /**  
23 - * 用户账号  
24 - */  
25 - private String username;  
26 -  
27 - /**  
28 - * 用户昵称  
29 - */  
30 - private String nickname;  
31 -  
32 - /**  
33 - * 用户邮箱  
34 - */  
35 - private String email;  
36 - /**  
37 - * 手机号码  
38 - */  
39 - private String mobile;  
40 -  
41 - /**  
42 - * 用户性别  
43 - */  
44 - private Integer sex;  
45 -  
46 - /**  
47 - * 用户头像  
48 - */  
49 - private String avatar;  
50 -  
51 - /**  
52 - * 所在部门  
53 - */  
54 - private Dept dept;  
55 -  
56 - /**  
57 - * 所属岗位数组  
58 - */  
59 - private List<Post> posts;  
60 -  
61 - /**  
62 - * 部门  
63 - */  
64 - @Data  
65 - public static class Dept {  
66 -  
67 - /**  
68 - * 部门编号  
69 - */  
70 - private Long id;  
71 -  
72 - /**  
73 - * 部门名称  
74 - */  
75 - private String name;  
76 -  
77 - }  
78 -  
79 - /**  
80 - * 岗位  
81 - */  
82 - @Data  
83 - public static class Post {  
84 -  
85 - /**  
86 - * 岗位编号  
87 - */  
88 - private Long id;  
89 -  
90 - /**  
91 - * 岗位名称  
92 - */  
93 - private String name;  
94 -  
95 - }  
96 -  
97 -}  
yudao-example/yudao-sso-demo-by-password/src/main/java/cn/iocoder/yudao/ssodemo/client/dto/user/UserUpdateReqDTO.java deleted
1 -package cn.iocoder.yudao.ssodemo.client.dto.user;  
2 -  
3 -import lombok.AllArgsConstructor;  
4 -import lombok.Data;  
5 -import lombok.NoArgsConstructor;  
6 -  
7 -/**  
8 - * 更新用户基本信息 Request DTO  
9 - */  
10 -@Data  
11 -@NoArgsConstructor  
12 -@AllArgsConstructor  
13 -public class UserUpdateReqDTO {  
14 -  
15 - /**  
16 - * 用户昵称  
17 - */  
18 - private String nickname;  
19 -  
20 - /**  
21 - * 用户邮箱  
22 - */  
23 - private String email;  
24 -  
25 - /**  
26 - * 手机号码  
27 - */  
28 - private String mobile;  
29 -  
30 - /**  
31 - * 用户性别  
32 - */  
33 - private Integer sex;  
34 -  
35 -}  
yudao-example/yudao-sso-demo-by-password/src/main/java/cn/iocoder/yudao/ssodemo/controller/AuthController.java deleted
1 -package cn.iocoder.yudao.ssodemo.controller;  
2 -  
3 -import cn.hutool.core.util.StrUtil;  
4 -import cn.iocoder.yudao.ssodemo.client.OAuth2Client;  
5 -import cn.iocoder.yudao.ssodemo.client.dto.CommonResult;  
6 -import cn.iocoder.yudao.ssodemo.client.dto.oauth2.OAuth2AccessTokenRespDTO;  
7 -import cn.iocoder.yudao.ssodemo.framework.core.util.SecurityUtils;  
8 -import org.springframework.web.bind.annotation.PostMapping;  
9 -import org.springframework.web.bind.annotation.RequestMapping;  
10 -import org.springframework.web.bind.annotation.RequestParam;  
11 -import org.springframework.web.bind.annotation.RestController;  
12 -  
13 -import jakarta.annotation.Resource;  
14 -import jakarta.servlet.http.HttpServletRequest;  
15 -  
16 -@RestController  
17 -@RequestMapping("/auth")  
18 -public class AuthController {  
19 -  
20 - @Resource  
21 - private OAuth2Client oauth2Client;  
22 -  
23 - /**  
24 - * 使用刷新令牌,获得(刷新)访问令牌  
25 - *  
26 - * @param refreshToken 刷新令牌  
27 - * @return 访问令牌;注意,实际项目中,最好创建对应的 ResponseVO 类,只返回必要的字段  
28 - */  
29 - @PostMapping("/refresh-token")  
30 - public CommonResult<OAuth2AccessTokenRespDTO> refreshToken(@RequestParam("refreshToken") String refreshToken) {  
31 - return oauth2Client.refreshToken(refreshToken);  
32 - }  
33 -  
34 - /**  
35 - * 退出登录  
36 - *  
37 - * @param request 请求  
38 - * @return 成功  
39 - */  
40 - @PostMapping("/logout")  
41 - public CommonResult<Boolean> logout(HttpServletRequest request) {  
42 - String token = SecurityUtils.obtainAuthorization(request, "Authorization");  
43 - if (StrUtil.isNotBlank(token)) {  
44 - return oauth2Client.revokeToken(token);  
45 - }  
46 - // 返回成功  
47 - return new CommonResult<>();  
48 - }  
49 -  
50 -}  
yudao-example/yudao-sso-demo-by-password/src/main/java/cn/iocoder/yudao/ssodemo/controller/UserController.java deleted
1 -package cn.iocoder.yudao.ssodemo.controller;  
2 -  
3 -import cn.iocoder.yudao.ssodemo.client.UserClient;  
4 -import cn.iocoder.yudao.ssodemo.client.dto.CommonResult;  
5 -import cn.iocoder.yudao.ssodemo.client.dto.user.UserInfoRespDTO;  
6 -import cn.iocoder.yudao.ssodemo.client.dto.user.UserUpdateReqDTO;  
7 -import org.springframework.web.bind.annotation.*;  
8 -  
9 -import jakarta.annotation.Resource;  
10 -  
11 -@RestController  
12 -@RequestMapping("/user")  
13 -public class UserController {  
14 -  
15 - @Resource  
16 - private UserClient userClient;  
17 -  
18 - /**  
19 - * 获得当前登录用户的基本信息  
20 - *  
21 - * @return 用户信息;注意,实际项目中,最好创建对应的 ResponseVO 类,只返回必要的字段  
22 - */  
23 - @GetMapping("/get")  
24 - public CommonResult<UserInfoRespDTO> getUser() {  
25 - return userClient.getUser();  
26 - }  
27 -  
28 - /**  
29 - * 更新当前登录用户的昵称  
30 - *  
31 - * @param nickname 昵称  
32 - * @return 成功  
33 - */  
34 - @PutMapping("/update")  
35 - public CommonResult<Boolean> updateUser(@RequestParam("nickname") String nickname) {  
36 - UserUpdateReqDTO updateReqDTO = new UserUpdateReqDTO(nickname, null, null, null);  
37 - return userClient.updateUser(updateReqDTO);  
38 - }  
39 -  
40 -}  
yudao-example/yudao-sso-demo-by-password/src/main/java/cn/iocoder/yudao/ssodemo/framework/config/SecurityConfiguration.java deleted
1 -package cn.iocoder.yudao.ssodemo.framework.config;  
2 -  
3 -import cn.iocoder.yudao.ssodemo.framework.core.filter.TokenAuthenticationFilter;  
4 -import cn.iocoder.yudao.ssodemo.framework.core.handler.AccessDeniedHandlerImpl;  
5 -import org.springframework.context.annotation.Bean;  
6 -import org.springframework.context.annotation.Configuration;  
7 -import org.springframework.http.HttpMethod;  
8 -import org.springframework.security.config.Customizer;  
9 -import org.springframework.security.config.annotation.web.builders.HttpSecurity;  
10 -import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;  
11 -import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;  
12 -import org.springframework.security.web.AuthenticationEntryPoint;  
13 -import org.springframework.security.web.SecurityFilterChain;  
14 -import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;  
15 -  
16 -import jakarta.annotation.Resource;  
17 -  
18 -@Configuration(proxyBeanMethods = false)  
19 -@EnableWebSecurity  
20 -public class SecurityConfiguration {  
21 -  
22 - @Resource  
23 - private TokenAuthenticationFilter tokenAuthenticationFilter;  
24 -  
25 - @Resource  
26 - private AccessDeniedHandlerImpl accessDeniedHandler;  
27 - @Resource  
28 - private AuthenticationEntryPoint authenticationEntryPoint;  
29 -  
30 - @Bean  
31 - protected SecurityFilterChain filterChain(HttpSecurity httpSecurity) throws Exception {  
32 - // 设置 URL 安全权限  
33 - httpSecurity  
34 - // 开启跨域  
35 - .cors(Customizer.withDefaults())  
36 - // CSRF 禁用,因为不使用 Session  
37 - .csrf(AbstractHttpConfigurer::disable)  
38 - // 一堆自定义的 Spring Security 处理器  
39 - .exceptionHandling(c -> c.authenticationEntryPoint(authenticationEntryPoint)  
40 - .accessDeniedHandler(accessDeniedHandler));  
41 -  
42 - // 设置每个请求的权限  
43 - httpSecurity.authorizeHttpRequests(c -> c  
44 - // 1. 静态资源,可匿名访问  
45 - .requestMatchers(HttpMethod.GET, "/*.html", "/*.html", "/*.css", "/*.js").permitAll()  
46 - // 2. 登录相关的接口,可匿名访问  
47 - .requestMatchers("/auth/login-by-code").permitAll()  
48 - .requestMatchers("/auth/refresh-token").permitAll()  
49 - .requestMatchers("/auth/logout").permitAll())  
50 - // 3. 兜底规则,必须认证  
51 - .authorizeHttpRequests(c -> c.anyRequest().authenticated());  
52 -  
53 - // 添加 Token Filter  
54 - httpSecurity.addFilterBefore(tokenAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);  
55 - return httpSecurity.build();  
56 - }  
57 -  
58 -}  
yudao-example/yudao-sso-demo-by-password/src/main/java/cn/iocoder/yudao/ssodemo/framework/core/LoginUser.java deleted
1 -package cn.iocoder.yudao.ssodemo.framework.core;  
2 -  
3 -import lombok.Data;  
4 -  
5 -import java.util.List;  
6 -  
7 -/**  
8 - * 登录用户信息  
9 - *  
10 - * @author 芋道源码  
11 - */  
12 -@Data  
13 -public class LoginUser {  
14 -  
15 - /**  
16 - * 用户编号  
17 - */  
18 - private Long id;  
19 - /**  
20 - * 用户类型  
21 - */  
22 - private Integer userType;  
23 - /**  
24 - * 租户编号  
25 - */  
26 - private Long tenantId;  
27 - /**  
28 - * 授权范围  
29 - */  
30 - private List<String> scopes;  
31 -  
32 - /**  
33 - * 访问令牌  
34 - */  
35 - private String accessToken;  
36 -  
37 -}  
yudao-example/yudao-sso-demo-by-password/src/main/java/cn/iocoder/yudao/ssodemo/framework/core/filter/TokenAuthenticationFilter.java deleted
1 -package cn.iocoder.yudao.ssodemo.framework.core.filter;  
2 -  
3 -import cn.iocoder.yudao.ssodemo.client.OAuth2Client;  
4 -import cn.iocoder.yudao.ssodemo.client.dto.CommonResult;  
5 -import cn.iocoder.yudao.ssodemo.client.dto.oauth2.OAuth2CheckTokenRespDTO;  
6 -import cn.iocoder.yudao.ssodemo.framework.core.LoginUser;  
7 -import cn.iocoder.yudao.ssodemo.framework.core.util.SecurityUtils;  
8 -import org.springframework.stereotype.Component;  
9 -import org.springframework.util.StringUtils;  
10 -import org.springframework.web.filter.OncePerRequestFilter;  
11 -  
12 -import jakarta.annotation.Resource;  
13 -import jakarta.servlet.FilterChain;  
14 -import jakarta.servlet.ServletException;  
15 -import jakarta.servlet.http.HttpServletRequest;  
16 -import jakarta.servlet.http.HttpServletResponse;  
17 -import java.io.IOException;  
18 -  
19 -/**  
20 - * Token 过滤器,验证 token 的有效性  
21 - * 验证通过后,获得 {@link LoginUser} 信息,并加入到 Spring Security 上下文  
22 - *  
23 - * @author 芋道源码  
24 - */  
25 -@Component  
26 -public class TokenAuthenticationFilter extends OncePerRequestFilter {  
27 -  
28 - @Resource  
29 - private OAuth2Client oauth2Client;  
30 -  
31 - @Override  
32 - protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,  
33 - FilterChain filterChain) throws ServletException, IOException {  
34 - // 1. 获得访问令牌  
35 - String token = SecurityUtils.obtainAuthorization(request, "Authorization");  
36 - if (StringUtils.hasText(token)) {  
37 - // 2. 基于 token 构建登录用户  
38 - LoginUser loginUser = buildLoginUserByToken(token);  
39 - // 3. 设置当前用户  
40 - if (loginUser != null) {  
41 - SecurityUtils.setLoginUser(loginUser, request);  
42 - }  
43 - }  
44 -  
45 - // 继续过滤链  
46 - filterChain.doFilter(request, response);  
47 - }  
48 -  
49 - private LoginUser buildLoginUserByToken(String token) {  
50 - try {  
51 - CommonResult<OAuth2CheckTokenRespDTO> accessTokenResult = oauth2Client.checkToken(token);  
52 - OAuth2CheckTokenRespDTO accessToken = accessTokenResult.getData();  
53 - if (accessToken == null) {  
54 - return null;  
55 - }  
56 - // 构建登录用户  
57 - return new LoginUser().setId(accessToken.getUserId()).setUserType(accessToken.getUserType())  
58 - .setTenantId(accessToken.getTenantId()).setScopes(accessToken.getScopes())  
59 - .setAccessToken(accessToken.getAccessToken());  
60 - } catch (Exception exception) {  
61 - // 校验 Token 不通过时,考虑到一些接口是无需登录的,所以直接返回 null 即可  
62 - return null;  
63 - }  
64 - }  
65 -  
66 -}  
yudao-example/yudao-sso-demo-by-password/src/main/java/cn/iocoder/yudao/ssodemo/framework/core/handler/AccessDeniedHandlerImpl.java deleted
1 -package cn.iocoder.yudao.ssodemo.framework.core.handler;  
2 -  
3 -import cn.iocoder.yudao.ssodemo.client.dto.CommonResult;  
4 -import cn.iocoder.yudao.ssodemo.framework.core.util.SecurityUtils;  
5 -import cn.iocoder.yudao.ssodemo.framework.core.util.ServletUtils;  
6 -import lombok.extern.slf4j.Slf4j;  
7 -import org.springframework.http.HttpStatus;  
8 -import org.springframework.security.access.AccessDeniedException;  
9 -import org.springframework.security.web.access.AccessDeniedHandler;  
10 -import org.springframework.security.web.access.ExceptionTranslationFilter;  
11 -import org.springframework.stereotype.Component;  
12 -  
13 -import jakarta.servlet.FilterChain;  
14 -import jakarta.servlet.ServletException;  
15 -import jakarta.servlet.http.HttpServletRequest;  
16 -import jakarta.servlet.http.HttpServletResponse;  
17 -import java.io.IOException;  
18 -  
19 -/**  
20 - * 访问一个需要认证的 URL 资源,已经认证(登录)但是没有权限的情况下,返回 {@link GlobalErrorCodeConstants#FORBIDDEN} 错误码。  
21 - *  
22 - * 补充:Spring Security 通过 {@link ExceptionTranslationFilter#handleAccessDeniedException(HttpServletRequest, HttpServletResponse, FilterChain, AccessDeniedException)} 方法,调用当前类  
23 - *  
24 - * @author 芋道源码  
25 - */  
26 -@Component  
27 -@SuppressWarnings("JavadocReference")  
28 -@Slf4j  
29 -public class AccessDeniedHandlerImpl implements AccessDeniedHandler {  
30 -  
31 - @Override  
32 - public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException e)  
33 - throws IOException, ServletException {  
34 - // 打印 warn 的原因是,不定期合并 warn,看看有没恶意破坏  
35 - log.warn("[commence][访问 URL({}) 时,用户({}) 权限不够]", request.getRequestURI(),  
36 - SecurityUtils.getLoginUserId(), e);  
37 - // 返回 403  
38 - CommonResult<Object> result = new CommonResult<>();  
39 - result.setCode(HttpStatus.FORBIDDEN.value());  
40 - result.setMsg("没有该操作权限");  
41 - ServletUtils.writeJSON(response, result);  
42 - }  
43 -  
44 -}  
yudao-example/yudao-sso-demo-by-password/src/main/java/cn/iocoder/yudao/ssodemo/framework/core/handler/AuthenticationEntryPointImpl.java deleted
1 -package cn.iocoder.yudao.ssodemo.framework.core.handler;  
2 -  
3 -import cn.iocoder.yudao.ssodemo.client.dto.CommonResult;  
4 -import cn.iocoder.yudao.ssodemo.framework.core.util.ServletUtils;  
5 -import lombok.extern.slf4j.Slf4j;  
6 -import org.springframework.http.HttpStatus;  
7 -import org.springframework.security.core.AuthenticationException;  
8 -import org.springframework.security.web.AuthenticationEntryPoint;  
9 -import org.springframework.security.web.access.ExceptionTranslationFilter;  
10 -import org.springframework.stereotype.Component;  
11 -  
12 -import jakarta.servlet.FilterChain;  
13 -import jakarta.servlet.http.HttpServletRequest;  
14 -import jakarta.servlet.http.HttpServletResponse;  
15 -  
16 -/**  
17 - * 访问一个需要认证的 URL 资源,但是此时自己尚未认证(登录)的情况下,返回 {@link GlobalErrorCodeConstants#UNAUTHORIZED} 错误码,从而使前端重定向到登录页  
18 - *  
19 - * 补充:Spring Security 通过 {@link ExceptionTranslationFilter#sendStartAuthentication(HttpServletRequest, HttpServletResponse, FilterChain, AuthenticationException)} 方法,调用当前类  
20 - */  
21 -@Component  
22 -@Slf4j  
23 -@SuppressWarnings("JavadocReference") // 忽略文档引用报错  
24 -public class AuthenticationEntryPointImpl implements AuthenticationEntryPoint {  
25 -  
26 - @Override  
27 - public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException e) {  
28 - log.debug("[commence][访问 URL({}) 时,没有登录]", request.getRequestURI(), e);  
29 - // 返回 401  
30 - CommonResult<Object> result = new CommonResult<>();  
31 - result.setCode(HttpStatus.UNAUTHORIZED.value());  
32 - result.setMsg("账号未登录");  
33 - ServletUtils.writeJSON(response, result);  
34 - }  
35 -  
36 -}  
yudao-example/yudao-sso-demo-by-password/src/main/java/cn/iocoder/yudao/ssodemo/framework/core/util/SecurityUtils.java deleted
1 -package cn.iocoder.yudao.ssodemo.framework.core.util;  
2 -  
3 -import cn.iocoder.yudao.ssodemo.framework.core.LoginUser;  
4 -import org.springframework.lang.Nullable;  
5 -import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;  
6 -import org.springframework.security.core.Authentication;  
7 -import org.springframework.security.core.context.SecurityContext;  
8 -import org.springframework.security.core.context.SecurityContextHolder;  
9 -import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;  
10 -import org.springframework.util.StringUtils;  
11 -  
12 -import jakarta.servlet.http.HttpServletRequest;  
13 -import java.util.Collections;  
14 -  
15 -/**  
16 - * 安全服务工具类  
17 - *  
18 - * @author 芋道源码  
19 - */  
20 -public class SecurityUtils {  
21 -  
22 - public static final String AUTHORIZATION_BEARER = "Bearer";  
23 -  
24 - private SecurityUtils() {}  
25 -  
26 - /**  
27 - * 从请求中,获得认证 Token  
28 - *  
29 - * @param request 请求  
30 - * @param header 认证 Token 对应的 Header 名字  
31 - * @return 认证 Token  
32 - */  
33 - public static String obtainAuthorization(HttpServletRequest request, String header) {  
34 - String authorization = request.getHeader(header);  
35 - if (!StringUtils.hasText(authorization)) {  
36 - return null;  
37 - }  
38 - int index = authorization.indexOf(AUTHORIZATION_BEARER + " ");  
39 - if (index == -1) { // 未找到  
40 - return null;  
41 - }  
42 - return authorization.substring(index + 7).trim();  
43 - }  
44 -  
45 - /**  
46 - * 获得当前认证信息  
47 - *  
48 - * @return 认证信息  
49 - */  
50 - public static Authentication getAuthentication() {  
51 - SecurityContext context = SecurityContextHolder.getContext();  
52 - if (context == null) {  
53 - return null;  
54 - }  
55 - return context.getAuthentication();  
56 - }  
57 -  
58 - /**  
59 - * 获取当前用户  
60 - *  
61 - * @return 当前用户  
62 - */  
63 - @Nullable  
64 - public static LoginUser getLoginUser() {  
65 - Authentication authentication = getAuthentication();  
66 - if (authentication == null) {  
67 - return null;  
68 - }  
69 - return authentication.getPrincipal() instanceof LoginUser ? (LoginUser) authentication.getPrincipal() : null;  
70 - }  
71 -  
72 - /**  
73 - * 获得当前用户的编号,从上下文中  
74 - *  
75 - * @return 用户编号  
76 - */  
77 - @Nullable  
78 - public static Long getLoginUserId() {  
79 - LoginUser loginUser = getLoginUser();  
80 - return loginUser != null ? loginUser.getId() : null;  
81 - }  
82 -  
83 - /**  
84 - * 设置当前用户  
85 - *  
86 - * @param loginUser 登录用户  
87 - * @param request 请求  
88 - */  
89 - public static void setLoginUser(LoginUser loginUser, HttpServletRequest request) {  
90 - // 创建 Authentication,并设置到上下文  
91 - Authentication authentication = buildAuthentication(loginUser, request);  
92 - SecurityContextHolder.getContext().setAuthentication(authentication);  
93 - }  
94 -  
95 - private static Authentication buildAuthentication(LoginUser loginUser, HttpServletRequest request) {  
96 - // 创建 UsernamePasswordAuthenticationToken 对象  
97 - UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(  
98 - loginUser, null, Collections.emptyList());  
99 - authenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));  
100 - return authenticationToken;  
101 - }  
102 -  
103 -}  
yudao-example/yudao-sso-demo-by-password/src/main/java/cn/iocoder/yudao/ssodemo/framework/core/util/ServletUtils.java deleted
1 -package cn.iocoder.yudao.ssodemo.framework.core.util;  
2 -  
3 -import cn.hutool.extra.servlet.JakartaServletUtil;  
4 -import cn.hutool.extra.servlet.ServletUtil;  
5 -import cn.hutool.json.JSONUtil;  
6 -import org.springframework.http.MediaType;  
7 -  
8 -import jakarta.servlet.http.HttpServletResponse;  
9 -  
10 -/**  
11 - * 客户端工具类  
12 - *  
13 - * @author 芋道源码  
14 - */  
15 -public class ServletUtils {  
16 -  
17 - /**  
18 - * 返回 JSON 字符串  
19 - *  
20 - * @param response 响应  
21 - * @param object 对象,会序列化成 JSON 字符串  
22 - */  
23 - @SuppressWarnings("deprecation") // 必须使用 APPLICATION_JSON_UTF8_VALUE,否则会乱码  
24 - public static void writeJSON(HttpServletResponse response, Object object) {  
25 - String content = JSONUtil.toJsonStr(object);  
26 - JakartaServletUtil.write(response, content, MediaType.APPLICATION_JSON_UTF8_VALUE);  
27 - }  
28 -  
29 - public static void write(HttpServletResponse response, String text, String contentType) {  
30 - JakartaServletUtil.write(response, text, contentType);  
31 - }  
32 -  
33 -}  
yudao-example/yudao-sso-demo-by-password/src/main/resources/application.yaml deleted
1 -server:  
2 - port: 18080  
yudao-example/yudao-sso-demo-by-password/src/main/resources/static/index.html deleted
1 -<!DOCTYPE html>  
2 -<html lang="en">  
3 -<head>  
4 - <meta charset="UTF-8">  
5 - <title>首页</title>  
6 - <!-- jQuery:操作 dom、发起请求等 -->  
7 - <script src="https://lf9-cdn-tos.bytecdntp.com/cdn/expire-1-M/jquery/2.1.2/jquery.min.js" type="application/javascript"></script>  
8 -  
9 - <script type="application/javascript">  
10 -  
11 - /**  
12 - * 跳转单点登录  
13 - */  
14 - function passwordLogin() {  
15 - window.location.href = '/login.html'  
16 - }  
17 -  
18 - /**  
19 - * 修改昵称  
20 - */  
21 - function updateNickname() {  
22 - const nickname = prompt("请输入新的昵称", "");  
23 - if (!nickname) {  
24 - return;  
25 - }  
26 - // 更新用户的昵称  
27 - const accessToken = localStorage.getItem('ACCESS-TOKEN');  
28 - $.ajax({  
29 - url: "http://127.0.0.1:18080/user/update?nickname=" + nickname,  
30 - method: 'PUT',  
31 - headers: {  
32 - 'Authorization': 'Bearer ' + accessToken  
33 - },  
34 - success: function (result) {  
35 - if (result.code !== 0) {  
36 - alert('更新昵称失败,原因:' + result.msg)  
37 - return;  
38 - }  
39 - alert('更新昵称成功!');  
40 - $('#nicknameSpan').html(nickname);  
41 - }  
42 - });  
43 - }  
44 -  
45 - /**  
46 - * 刷新令牌  
47 - */  
48 - function refreshToken() {  
49 - const refreshToken = localStorage.getItem('REFRESH-TOKEN');  
50 - if (!refreshToken) {  
51 - alert("获取不到刷新令牌");  
52 - return;  
53 - }  
54 - $.ajax({  
55 - url: "http://127.0.0.1:18080/auth/refresh-token?refreshToken=" + refreshToken,  
56 - method: 'POST',  
57 - success: function (result) {  
58 - if (result.code !== 0) {  
59 - alert('刷新访问令牌失败,原因:' + result.msg)  
60 - return;  
61 - }  
62 - alert('更新访问令牌成功!');  
63 - $('#accessTokenSpan').html(result.data.access_token);  
64 -  
65 - // 设置到 localStorage 中  
66 - localStorage.setItem('ACCESS-TOKEN', result.data.access_token);  
67 - localStorage.setItem('REFRESH-TOKEN', result.data.refresh_token);  
68 - }  
69 - });  
70 - }  
71 -  
72 - /**  
73 - * 登出,删除访问令牌  
74 - */  
75 - function logout() {  
76 - const accessToken = localStorage.getItem('ACCESS-TOKEN');  
77 - if (!accessToken) {  
78 - location.reload();  
79 - return;  
80 - }  
81 - $.ajax({  
82 - url: "http://127.0.0.1:18080/auth/logout",  
83 - method: 'POST',  
84 - headers: {  
85 - 'Authorization': 'Bearer ' + accessToken  
86 - },  
87 - success: function (result) {  
88 - if (result.code !== 0) {  
89 - alert('退出登录失败,原因:' + result.msg)  
90 - return;  
91 - }  
92 - alert('退出登录成功!');  
93 - // 删除 localStorage 中  
94 - localStorage.removeItem('ACCESS-TOKEN');  
95 - localStorage.removeItem('REFRESH-TOKEN');  
96 -  
97 - location.reload();  
98 - }  
99 - });  
100 - }  
101 -  
102 - $(function () {  
103 - const accessToken = localStorage.getItem('ACCESS-TOKEN');  
104 - // 情况一:未登录  
105 - if (!accessToken) {  
106 - $('#noLoginDiv').css("display", "block");  
107 - return;  
108 - }  
109 -  
110 - // 情况二:已登录  
111 - $('#yesLoginDiv').css("display", "block");  
112 - $('#accessTokenSpan').html(accessToken);  
113 - // 获得登录用户的信息  
114 - $.ajax({  
115 - url: "http://127.0.0.1:18080/user/get",  
116 - method: 'GET',  
117 - headers: {  
118 - 'Authorization': 'Bearer ' + accessToken  
119 - },  
120 - success: function (result) {  
121 - if (result.code !== 0) {  
122 - alert('获得个人信息失败,原因:' + result.msg)  
123 - return;  
124 - }  
125 - $('#nicknameSpan').html(result.data.nickname);  
126 - }  
127 - });  
128 - })  
129 - </script>  
130 -</head>  
131 -<body>  
132 -<!-- 情况一:未登录:1)跳转 ruoyi-vue-pro 的 SSO 登录页 -->  
133 -<div id="noLoginDiv" style="display: none">  
134 - 您未登录,点击 <a href="#" onclick="passwordLogin()">跳转 </a> 账号密码登录  
135 -</div>  
136 -  
137 -<!-- 情况二:已登录:1)展示用户信息;2)刷新访问令牌;3)退出登录 -->  
138 -<div id="yesLoginDiv" style="display: none">  
139 - 您已登录!<button onclick="logout()">退出登录</button> <br />  
140 - 昵称:<span id="nicknameSpan"> 加载中... </span> <button onclick="updateNickname()">修改昵称</button> <br />  
141 - 访问令牌:<span id="accessTokenSpan"> 加载中... </span> <button onclick="refreshToken()">刷新令牌</button> <br />  
142 -</div>  
143 -</body>  
144 -<style>  
145 - body { /** 页面居中 */  
146 - border-radius: 20px;  
147 - height: 350px;  
148 - position: absolute;  
149 - left: 50%;  
150 - top: 50%;  
151 - transform: translate(-50%,-50%);  
152 - }  
153 -</style>  
154 -</html>  
yudao-example/yudao-sso-demo-by-password/src/main/resources/static/login.html deleted
1 -<!DOCTYPE html>  
2 -<html lang="en">  
3 -<head>  
4 - <meta charset="UTF-8">  
5 - <title>登录</title>  
6 - <!-- jQuery:操作 dom、发起请求等 -->  
7 - <script src="https://lf9-cdn-tos.bytecdntp.com/cdn/expire-1-M/jquery/2.1.2/jquery.min.js" type="application/javascript"></script>  
8 -  
9 - <script type="application/javascript">  
10 -  
11 - /**  
12 - * 账号密码登录  
13 - */  
14 - function login() {  
15 - const clientId = 'yudao-sso-demo-by-password'; // 可以改写成,你的 clientId  
16 - const clientSecret = 'test'; // 可以改写成,你的 clientSecret  
17 - const grantType = 'password'; // 密码模式  
18 -  
19 - // 账号 + 密码  
20 - const username = $('#username').val();  
21 - const password = $('#password').val();  
22 - if (username.length === 0 || password.length === 0) {  
23 - alert('账号或密码未输入');  
24 - return;  
25 - }  
26 -  
27 - // 发起请求  
28 - $.ajax({  
29 - url: "http://127.0.0.1:48080/admin-api/system/oauth2/token?"  
30 - // 客户端  
31 - + "client_id=" + clientId  
32 - + "&client_secret=" + clientSecret  
33 - // 密码模式的参数  
34 - + "&grant_type=" + grantType  
35 - + "&username=" + username  
36 - + "&password=" + password  
37 - + '&scope=user.read user.write',  
38 - method: 'POST',  
39 - headers: {  
40 - 'tenant-id': '1', // 多租户编号,写死  
41 - },  
42 - success: function (result) {  
43 - if (result.code !== 0) {  
44 - alert('登录失败,原因:' + result.msg)  
45 - return;  
46 - }  
47 - // 设置到 localStorage 中  
48 - localStorage.setItem('ACCESS-TOKEN', result.data.access_token);  
49 - localStorage.setItem('REFRESH-TOKEN', result.data.refresh_token);  
50 -  
51 - // 提示登录成功  
52 - alert('登录成功!点击确认,跳转回首页');  
53 - window.location.href = '/index.html';  
54 - }  
55 - });  
56 - }  
57 - </script>  
58 -</head>  
59 -<body>  
60 -账号:<input id="username" value="admin" /> <br />  
61 -密码:<input id="password" value="admin123" > <br />  
62 -<button style="float: right; margin-top: 5px;" onclick="login()">登录</button>  
63 -</body>  
64 -<style>  
65 - body { /** 页面居中 */  
66 - border-radius: 20px;  
67 - height: 350px;  
68 - position: absolute;  
69 - left: 50%;  
70 - top: 50%;  
71 - transform: translate(-50%,-50%);  
72 - }  
73 -</style>  
74 -</html>