├── .gitignore
├── README.md
├── authorization-code
├── README.md
├── authorization-code-authorization-server
│ ├── pom.xml
│ └── src
│ │ └── main
│ │ ├── java
│ │ └── com
│ │ │ └── github
│ │ │ └── hellxz
│ │ │ └── oauth2
│ │ │ ├── AuthorizationCodeAuthorizationServerApp.java
│ │ │ └── config
│ │ │ ├── AuthorizationConfig.java
│ │ │ └── SecurityConfig.java
│ │ └── resources
│ │ └── application.properties
├── authorization-code-client-resttemplate-jdbc
│ ├── README.md
│ ├── pom.xml
│ └── src
│ │ ├── main
│ │ ├── java
│ │ │ └── com
│ │ │ │ └── github
│ │ │ │ └── hellxz
│ │ │ │ └── oauth2
│ │ │ │ ├── AuthorizationCodeClientApp.java
│ │ │ │ ├── config
│ │ │ │ ├── ClientAuthenticationManager.java
│ │ │ │ ├── ClientUserDetailsService.java
│ │ │ │ ├── OAuth2ClientProperties.java
│ │ │ │ ├── OAuth2ServerProperties.java
│ │ │ │ └── SecurityConfig.java
│ │ │ │ ├── consts
│ │ │ │ └── GrantType.java
│ │ │ │ ├── dao
│ │ │ │ └── ClientUserRepositories.java
│ │ │ │ ├── domain
│ │ │ │ └── ClientUser.java
│ │ │ │ ├── dto
│ │ │ │ └── TokenDTO.java
│ │ │ │ ├── service
│ │ │ │ ├── ClientUserService.java
│ │ │ │ └── TokenService.java
│ │ │ │ ├── utils
│ │ │ │ └── SecurityUtils.java
│ │ │ │ └── web
│ │ │ │ ├── MainPageController.java
│ │ │ │ └── vo
│ │ │ │ └── UserInfo.java
│ │ └── resources
│ │ │ ├── application.yml
│ │ │ ├── sql
│ │ │ └── create_table.sql
│ │ │ └── templates
│ │ │ ├── index.html
│ │ │ └── user-info.html
│ │ └── test
│ │ └── java
│ │ └── com
│ │ └── github
│ │ └── hellxz
│ │ └── oauth2
│ │ └── ClientUserTests.java
├── authorization-code-resource-server
│ ├── pom.xml
│ └── src
│ │ └── main
│ │ ├── java
│ │ └── com
│ │ │ └── github
│ │ │ └── hellxz
│ │ │ └── oauth2
│ │ │ ├── AuthorizationCodeResourceServerApp.java
│ │ │ ├── config
│ │ │ └── ResourceConfig.java
│ │ │ └── web
│ │ │ ├── controller
│ │ │ └── ResourceController.java
│ │ │ └── vo
│ │ │ └── UserVO.java
│ │ └── resources
│ │ └── application.properties
└── pom.xml
├── client-credentials
├── README.md
├── client-credentials-authorization-server
│ ├── pom.xml
│ └── src
│ │ └── main
│ │ ├── java
│ │ └── com
│ │ │ └── github
│ │ │ └── hellxz
│ │ │ └── oauth2
│ │ │ ├── ClientCredentialsAuthorizationApp.java
│ │ │ └── config
│ │ │ ├── AuthorizationConfig.java
│ │ │ └── SecurityConfig.java
│ │ └── resources
│ │ └── application.properties
├── client-credentials-client
│ ├── pom.xml
│ └── src
│ │ └── main
│ │ ├── java
│ │ └── com
│ │ │ └── github
│ │ │ └── hellxz
│ │ │ └── oauth2
│ │ │ ├── ClientCredentialsClientApp.java
│ │ │ ├── config
│ │ │ ├── SecureConfig.java
│ │ │ └── UaaProperties.java
│ │ │ ├── dto
│ │ │ └── UserDto.java
│ │ │ ├── feign
│ │ │ ├── UserFeignClient.java
│ │ │ └── fallback
│ │ │ │ └── UserFeignClientFallback.java
│ │ │ ├── filter
│ │ │ └── FeignTokenInterceptor.java
│ │ │ ├── utils
│ │ │ └── TokenUtils.java
│ │ │ └── web
│ │ │ └── UserController.java
│ │ └── resources
│ │ └── application.yml
├── client-credentials-resource-server
│ ├── pom.xml
│ └── src
│ │ └── main
│ │ ├── java
│ │ └── com
│ │ │ └── github
│ │ │ └── hellxz
│ │ │ └── oauth2
│ │ │ ├── ClientCredentialsResourceServerApp.java
│ │ │ ├── config
│ │ │ └── ResourceServerConfig.java
│ │ │ └── web
│ │ │ ├── controller
│ │ │ └── ResourceController.java
│ │ │ └── vo
│ │ │ └── UserVO.java
│ │ └── resources
│ │ └── application.properties
└── pom.xml
├── implicit
├── README.md
├── implicit-authorization-server
│ ├── pom.xml
│ └── src
│ │ └── main
│ │ ├── java
│ │ └── com
│ │ │ └── github
│ │ │ └── hellxz
│ │ │ └── oauth2
│ │ │ ├── ImplicitAuthorizationServerApplication.java
│ │ │ └── config
│ │ │ ├── AuthorizationConfig.java
│ │ │ └── SecurityConfig.java
│ │ └── resources
│ │ └── application.properties
├── implicit-resource-server
│ ├── pom.xml
│ └── src
│ │ └── main
│ │ ├── java
│ │ └── com
│ │ │ └── github
│ │ │ └── hellxz
│ │ │ └── oauth2
│ │ │ ├── ImplicitResourceServerApp.java
│ │ │ ├── config
│ │ │ └── ResourceConfig.java
│ │ │ └── web
│ │ │ ├── controller
│ │ │ └── ResourceController.java
│ │ │ └── vo
│ │ │ └── UserVO.java
│ │ └── resources
│ │ └── application.properties
└── pom.xml
├── jwt
├── README.md
├── jwt-authorization-server
│ ├── pom.xml
│ └── src
│ │ └── main
│ │ ├── java
│ │ └── com
│ │ │ └── github
│ │ │ └── hellxz
│ │ │ └── oauth2
│ │ │ ├── JwtAuthorizationServerApp.java
│ │ │ └── config
│ │ │ ├── AuthorizationConfig.java
│ │ │ └── SecurityConfig.java
│ │ └── resources
│ │ ├── application.properties
│ │ └── hellxz-jwt.jks
├── jwt-resource-server
│ ├── pom.xml
│ └── src
│ │ └── main
│ │ ├── java
│ │ └── com
│ │ │ └── github
│ │ │ └── hellxz
│ │ │ └── oauth2
│ │ │ ├── JwtResourceServerApp.java
│ │ │ ├── config
│ │ │ └── ResourceConfig.java
│ │ │ └── web
│ │ │ ├── controller
│ │ │ └── ResourceController.java
│ │ │ └── vo
│ │ │ └── UserVO.java
│ │ └── resources
│ │ ├── application.properties
│ │ └── public.cert
└── pom.xml
├── password
├── README.md
├── password-authorization-server
│ ├── pom.xml
│ └── src
│ │ └── main
│ │ ├── java
│ │ └── com
│ │ │ └── github
│ │ │ └── hellxz
│ │ │ └── oauth2
│ │ │ ├── PasswordAuthorizationApp.java
│ │ │ └── config
│ │ │ ├── AuthorizationConfig.java
│ │ │ └── SecurityConfig.java
│ │ └── resources
│ │ └── application.properties
├── password-resource-server
│ ├── pom.xml
│ └── src
│ │ └── main
│ │ ├── java
│ │ └── com
│ │ │ └── github
│ │ │ └── hellxz
│ │ │ └── oauth2
│ │ │ ├── PasswordResourceApp.java
│ │ │ ├── config
│ │ │ └── ResourceServerConfig.java
│ │ │ └── web
│ │ │ ├── controller
│ │ │ └── ResourceController.java
│ │ │ └── vo
│ │ │ └── UserVO.java
│ │ └── resources
│ │ └── application.properties
└── pom.xml
├── pictures
└── encoded-jwt3.png
├── pom.xml
├── redis-token-saved
├── README.md
├── pom.xml
├── redis-token-saved-authorization-server
│ ├── pom.xml
│ └── src
│ │ ├── main
│ │ ├── java
│ │ │ └── com
│ │ │ │ └── github
│ │ │ │ └── hellxz
│ │ │ │ └── oauth2
│ │ │ │ ├── RedisAuthorizationServer.java
│ │ │ │ └── config
│ │ │ │ ├── AuthorizationConfig.java
│ │ │ │ └── SecurityConfig.java
│ │ └── resources
│ │ │ └── application.yml
│ │ └── test
│ │ └── java
│ │ └── com
│ │ └── github
│ │ └── hellxz
│ │ └── auth2
│ │ └── RedisTokenSavedServerTest.java
└── redis-token-saved-resource-server
│ ├── pom.xml
│ └── src
│ └── main
│ ├── java
│ └── com
│ │ └── github
│ │ └── hellxz
│ │ └── oauth2
│ │ ├── RedisResourceServer.java
│ │ ├── config
│ │ └── ResourceServerConfig.java
│ │ └── web
│ │ ├── controller
│ │ └── ResourceController.java
│ │ └── vo
│ │ └── UserVO.java
│ └── resources
│ └── application.yml
└── uaa-interface-adapter-demo
├── README.md
├── pom.xml
└── src
└── main
├── java
└── com
│ └── github
│ └── hellxz
│ └── oauth2
│ └── demo
│ ├── UaaAdapterApplication.java
│ ├── config
│ └── WebSecurityConfig.java
│ ├── controller
│ └── UaaAdapterController.java
│ └── utils
│ └── Response.java
└── resources
└── application.yml
/.gitignore:
--------------------------------------------------------------------------------
1 | /spring-security-oauth2-learn.iml
2 | .idea
3 | *.iml
4 | **/target
5 | **/.classpath
6 | **/.project
7 | **/.settings
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # spring-security-oauth2-learn
2 | ## 仓库说明
3 | 此项目用于学习Spring Security OAuth2,Demo使用的Api为5.2版本前的,现在提示已经废弃,ps:最初官方认为自己的授权服务器实现的太差就移除了,后来社区广泛需要授权服务器,官方又重新开发了`spring-security-oauth2-authorization-server
4 |
5 | 后续等官方授权服务器稳定后,本人会继续更新一个基于它的demo。相比此仓库的demo基于OAuth2.0实现,新的授权服务器是基于OAuth2.1协议的。
6 |
7 | 另外,本仓库均使用授权服务与资源服务分离的方式来编写demo,由于此二者放在同一服务时默认省了很多配置(资源服务器访问授权服务器进行校验token部分),对于后续应用会埋下许多坑,所以分离开来
8 |
9 | ## 基础演示demo功能说明
10 | > 基础Demo均使用内存保存token,仅用于测试
11 |
12 | - [x] authorization-code : 授权码模式
13 |
14 | - [x] client-credentials : 客户端模式
15 |
16 | - [x] implicit: 隐式模式(简化模式)
17 |
18 | - [x] password: 密码模式
19 |
20 | ## client端对接demo
21 | - [x] authorization-code/authorization-code-client-resttemplate-jdbc : 使用RestTemplate和数据库实现的授权码模式手动对接客户端,token保存到数据库
22 | - [x] uaa-interface-adapter-demo : 使用OAuth2提供的工具类,实现的客户端模式与密码模式的登录功能适配,也可以作为不显示使用/oauth/token端点的适配层,提升代码灵活性
23 | - [x] client-credentials/client-credentials-client: 实现一个客户端,如果调用其它服务的请求头中没有登录标识,使用客户端模式获取token,调用其它服务
24 |
25 | ## JWT
26 | > 使用rsa非对称加密,对称加密请参考本目录之前的提交
27 |
28 | - [x] jwt-authorization-server : 添加JWT实现token的授权服务器,这里开启了授权码与密码模式,支持refresh_token
29 | - [x] jwt-resource-server:资源服务器,本地校验jwt token,解析出用户信息
30 |
31 | ## 使用Redis存储token
32 | - [x] redis-token-saved-authorization-server : 使用password与授权码模式,支持刷新token的授权服务器,token保存到redis中
33 | - [x] redis-token-saved-resource-server : 使用redis校验token的资源服务器
34 |
35 |
36 |
--------------------------------------------------------------------------------
/authorization-code/README.md:
--------------------------------------------------------------------------------
1 | # 授权码模式Demo
2 | 此文档测试对象为`authorization-code-authorization-server`和`authorization-code-resource-server`
3 | ## 1. 获取授权码
4 | 1. 用户(资源拥有者)浏览器访问
5 | `http://localhost:8080/oauth/authorize?client_id=client-a&redirect_uri=http://localhost:9001/callback&response_type=code&scope=read_user_info`
6 | 请求参数列表:
7 | - client_id=客户端id
8 | - redirect_uri=回调url 一定要与授权服务器配置保持一致,否则得不到授权码
9 | - response_type=code 授权码必须是code
10 | - scope=作用域 与授权服务器配置保持一致
11 | - state=加密串或状态标识(可选)
12 |
13 | 2. 使用hellxz用户登录,用户名hellxz,密码xyz
14 | > 这里使用授权服务器中的用户登录
15 |
16 | 3. 选择`Approve`,点`Authorize`提交, 完成授权操作
17 | 4. 服务器校验通过,在回调url参数后添加`?code=授权码`并重定向
18 | > 回调的url对应一个服务接口,接收授权码并使用其换取令牌,下边授权码换令牌步骤使用手动方式测试
19 |
20 | ## 2. 授权码换令牌
21 | > 换取令牌操作为服务器进行操作的,这里登录用户需要是客户端的标识与secret
22 |
23 | 1. 发送Post请求到`http://localhost:8080/oauth/token`
24 | 请求参数列表:
25 | - code=授权码
26 | - grant_type=authorization_code
27 | - redirect_uri=回调url
28 | - scope=作用域
29 |
30 | 请求头列表:
31 | - Authorization:Basic 经Base64加密后的username:password的字符串
32 |
33 | ```
34 | curl -X POST \
35 | http://localhost:8080/oauth/token \
36 | -H 'Authorization: Basic Y2xpZW50LWE6Y2xpZW50LWEtc2VjcmV0' \
37 | -d 'code=TJb4Pd&grant_type=authorization_code&redirect_uri=http%3A%2F%2Flocalhost%3A9001%2Fcallback&scope=read_user_info'
38 | ```
39 |
40 | 获得令牌
41 | ```json
42 | {
43 | "access_token": "3ed92b8a-86f0-4ee1-b309-7db0b513f554",
44 | "token_type": "bearer",
45 | "expires_in": 43199,
46 | "scope": "read_user_info"
47 | }
48 | ```
49 |
50 | ## 3. 校验Token
51 |
52 | 这里测试下授权服务的令牌校验端点`/oauth/check_token`
53 | 1. 发送Post请求`http://localhost:8080/oauth/check_token`
54 | 请求参数列表:
55 | - token=令牌
56 | 请求头参数:
57 | - Authorization=Basic Y2xpZW50LWE6Y2xpZW50LWEtc2VjcmV0
58 |
59 | ```
60 | curl -X POST http://localhost:8080/oauth/check_token \
61 | -H 'Authorization: Basic Y2xpZW50LWE6Y2xpZW50LWEtc2VjcmV0' \
62 | -d 'token=3ed92b8a-86f0-4ee1-b309-7db0b513f554'
63 | ```
64 |
65 | 返回请求体:
66 | ```json
67 | {
68 | "aud": [
69 | "resource1"
70 | ],
71 | "active": true,
72 | "exp": 1574724686,
73 | "user_name": "hellxz",
74 | "client_id": "client-a",
75 | "scope": [
76 | "read_user_info"
77 | ]
78 | }
79 | ```
80 | 至此,我们确保了授权服务器的接口是正常的
81 |
82 | ## 4. 使用token访问受保护的资源
83 | 1. 发起请求`http://localhost:8081/user/hellxz001`
84 | 请求头参数:
85 | - Authorization:Bearer 令牌值 这里要注意的是Bearer与token间有一个空格
86 |
87 | ```bash
88 | curl -X GET http://localhost:8081/user/hellxz001 \
89 | -H 'Authorization: Bearer ca3c1d03-67b8-4e39-b2b3-0d634f094610'
90 | ```
91 |
92 | 返回结果
93 | ```json
94 | {
95 | "username": "hellxz001",
96 | "email": "hellxz001@foxmail.com"
97 | }
98 | ```
99 |
100 | ## 授权码流程梳理
101 | 1. 用户通过客户端(浏览器等)的接口 客户端本地检查是否有令牌,没有则拼接请求授权服务器的url重定向给用户,有则使用令牌尝试访问,如果请求过期,重新走授权
102 | 2. 用户访问到授权服务器页面,用户登录,并进行授权
103 | 3. 授权通过,授权服务器返回code(授权码)到回调的客户端url上
104 | 4. 客户端收到授权码,带上授权码向授权服务器发起请求, 获取token
105 | 4. 授权服务器根据传递过来的客户端的client_id、client_secret、授权码进行校验,校验通过返回access_token
106 | 5. 客户端收到token,将token保存在本地,请求时带上token,接着自调用接口,访问资源服务器的资源
107 |
108 | > 这里暂未写客户端(浏览器这部分),通过手动获取资源以了解授权码模式整体授权流程
--------------------------------------------------------------------------------
/authorization-code/authorization-code-authorization-server/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 | authorization-code
7 | com.github.hellxz
8 | 0.0.1-SNAPSHOT
9 |
10 | 4.0.0
11 |
12 | authorization-code-authorization-server
13 |
--------------------------------------------------------------------------------
/authorization-code/authorization-code-authorization-server/src/main/java/com/github/hellxz/oauth2/AuthorizationCodeAuthorizationServerApp.java:
--------------------------------------------------------------------------------
1 | package com.github.hellxz.oauth2;
2 |
3 | import org.springframework.boot.SpringApplication;
4 | import org.springframework.boot.autoconfigure.SpringBootApplication;
5 |
6 | /**
7 | * 授权服务器 入口
8 | *
9 | * @author hellxz
10 | */
11 | @SpringBootApplication
12 | public class AuthorizationCodeAuthorizationServerApp {
13 |
14 | public static void main(String[] args) {
15 | SpringApplication.run(AuthorizationCodeAuthorizationServerApp.class, args);
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/authorization-code/authorization-code-authorization-server/src/main/java/com/github/hellxz/oauth2/config/AuthorizationConfig.java:
--------------------------------------------------------------------------------
1 | package com.github.hellxz.oauth2.config;
2 |
3 | import org.springframework.beans.factory.annotation.Autowired;
4 | import org.springframework.context.annotation.Configuration;
5 | import org.springframework.security.crypto.password.PasswordEncoder;
6 | import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
7 | import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
8 | import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
9 | import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
10 |
11 | //授权服务器配置
12 | @Configuration
13 | @EnableAuthorizationServer //开启授权服务
14 | public class AuthorizationConfig extends AuthorizationServerConfigurerAdapter {
15 |
16 | @Autowired
17 | private PasswordEncoder passwordEncoder;
18 |
19 | @Override
20 | public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
21 | //允许表单提交
22 | security.allowFormAuthenticationForClients()
23 | .checkTokenAccess("isAuthenticated()");
24 | }
25 |
26 | @Override
27 | public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
28 | // @formatter: off
29 | clients.inMemory()
30 | .withClient("client-a") //客户端唯一标识(client_id)
31 | .secret(passwordEncoder.encode("client-a-secret")) //客户端的密码(client_secret),这里的密码应该是加密后的
32 | .authorizedGrantTypes("authorization_code") //授权模式标识
33 | .scopes("read_user_info") //作用域
34 | .resourceIds("resource1") //资源id
35 | .redirectUris("http://localhost:9001/callback"); //回调地址
36 | // @formatter: on
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/authorization-code/authorization-code-authorization-server/src/main/java/com/github/hellxz/oauth2/config/SecurityConfig.java:
--------------------------------------------------------------------------------
1 | package com.github.hellxz.oauth2.config;
2 |
3 | import org.springframework.context.annotation.Bean;
4 | import org.springframework.context.annotation.Configuration;
5 | import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
6 | import org.springframework.security.config.annotation.web.builders.HttpSecurity;
7 | import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
8 | import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
9 | import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
10 | import org.springframework.security.crypto.password.PasswordEncoder;
11 |
12 | import java.util.Collections;
13 |
14 | @Configuration
15 | @EnableWebSecurity
16 | public class SecurityConfig extends WebSecurityConfigurerAdapter {
17 |
18 | @Bean
19 | public PasswordEncoder passwordEncoder(){
20 | return new BCryptPasswordEncoder();
21 | }
22 |
23 | @Override
24 | protected void configure(AuthenticationManagerBuilder auth) throws Exception {
25 | // @formatter: off
26 | auth.inMemoryAuthentication()
27 | .withUser("hellxz")
28 | .password(passwordEncoder().encode("xyz"))
29 | .authorities(Collections.emptyList());
30 | // @formatter: on
31 | }
32 |
33 | @Override
34 | protected void configure(HttpSecurity http) throws Exception {
35 | http.authorizeRequests()
36 | .anyRequest().authenticated() //所有请求都需要通过认证
37 | .and()
38 | .httpBasic() //Basic提交
39 | .and()
40 | .csrf().disable(); //关跨域保护
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/authorization-code/authorization-code-authorization-server/src/main/resources/application.properties:
--------------------------------------------------------------------------------
1 | server.port=8080
--------------------------------------------------------------------------------
/authorization-code/authorization-code-client-resttemplate-jdbc/README.md:
--------------------------------------------------------------------------------
1 | # 接入授权码模式客户端使用RestTemplate实现
2 | ## 说明
3 | 这里使用RestTemplate作为客户端,对接我们的授权码模式的授权服务器和资源服务器,客户端token存储使用数据库实现(仅用作demo)
4 | ## 操作流程
5 | 1. 启动授权码授权服务器
6 | 2. 启动授权码资源服务器
7 | 3. 数据库修改并执行`resource/create_table.sql`,启动此项目
8 | 4. 访问`http://localhost:9001`点击`点此进入用户详情页`
9 | 5. 使用`hellxz`:`abc`登录,这里登录的是客户端服务器
10 | 6. 使用`hellxz`:`xyz`登录,这里登录的是授权服务器
11 | 7. 进行授权操作
12 | 8. 自动重定向到访问的资源页面
13 | ## 内部流程说明
14 | - 访问授权详情页时,由于资源被拦截,会弹出登录窗口,登录客户端用户
15 | - 进行用户详情页对应的controller,查数据库看`oauth2_client_db.client_user`表中是否有用户token
16 | - 如果有,使用此token尝试调用资源服务器,没有则去调用授权服务器,获取授权码
17 | - 授权服务器返回授权码到客户端的回调接口`/callback`
18 | - 回调接口中,使用授权码换取token,获取token后保存到数据库与当前security上下文
19 | - 重定向原来的页面,再走一次访问资源服务器调用,如果报错`HttpClientErrorException`,则捕获异常并重走授权(token已过期)
20 | - 最后一切正常,放置资源服务器得到的数据并跳转到页面,进行展示
--------------------------------------------------------------------------------
/authorization-code/authorization-code-client-resttemplate-jdbc/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 | authorization-code
7 | com.github.hellxz
8 | 0.0.1-SNAPSHOT
9 |
10 | 4.0.0
11 |
12 | authorization-code-client-resttemplate-jdbc
13 |
14 |
15 |
16 | org.springframework.boot
17 | spring-boot-starter-thymeleaf
18 |
19 |
20 | org.springframework.boot
21 | spring-boot-starter-data-jpa
22 |
23 |
24 | mysql
25 | mysql-connector-java
26 |
27 |
28 | org.apache.commons
29 | commons-lang3
30 |
31 |
32 |
--------------------------------------------------------------------------------
/authorization-code/authorization-code-client-resttemplate-jdbc/src/main/java/com/github/hellxz/oauth2/AuthorizationCodeClientApp.java:
--------------------------------------------------------------------------------
1 | package com.github.hellxz.oauth2;
2 |
3 | import org.springframework.boot.SpringApplication;
4 | import org.springframework.boot.autoconfigure.SpringBootApplication;
5 | import org.springframework.context.annotation.Bean;
6 | import org.springframework.web.client.RestTemplate;
7 |
8 | @SpringBootApplication
9 | public class AuthorizationCodeClientApp {
10 | public static void main(String[] args) {
11 | SpringApplication.run(AuthorizationCodeClientApp.class, args);
12 | }
13 |
14 | @Bean
15 | public RestTemplate restTemplate(){
16 | return new RestTemplate();
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/authorization-code/authorization-code-client-resttemplate-jdbc/src/main/java/com/github/hellxz/oauth2/config/ClientAuthenticationManager.java:
--------------------------------------------------------------------------------
1 | package com.github.hellxz.oauth2.config;
2 |
3 | import com.github.hellxz.oauth2.dao.ClientUserRepositories;
4 | import org.apache.commons.lang3.StringUtils;
5 | import org.springframework.beans.factory.annotation.Autowired;
6 | import org.springframework.security.authentication.AuthenticationManager;
7 | import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
8 | import org.springframework.security.core.Authentication;
9 | import org.springframework.security.core.AuthenticationException;
10 | import org.springframework.security.core.userdetails.UserDetails;
11 | import org.springframework.stereotype.Component;
12 |
13 | @Component
14 | public class ClientAuthenticationManager implements AuthenticationManager {
15 |
16 | @Autowired
17 | private ClientUserDetailsService clientUserDetailsService;
18 |
19 | @Override
20 | public Authentication authenticate(Authentication authentication) throws AuthenticationException {
21 | UserDetails principal = (UserDetails) authentication.getPrincipal();
22 | String username = principal.getUsername();
23 | String password = principal.getPassword();
24 | if (StringUtils.isAnyBlank(username, password)) {
25 | throw new RuntimeException("用户名与密码均不能为空");
26 | }
27 | UserDetails userDetails = clientUserDetailsService.loadUserByUsername(username);
28 | if (!StringUtils.equals(password, userDetails.getPassword())) {
29 | throw new RuntimeException("密码输入不正确!");
30 | }
31 | return new UsernamePasswordAuthenticationToken(userDetails.getUsername(), userDetails.getPassword());
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/authorization-code/authorization-code-client-resttemplate-jdbc/src/main/java/com/github/hellxz/oauth2/config/ClientUserDetailsService.java:
--------------------------------------------------------------------------------
1 | package com.github.hellxz.oauth2.config;
2 |
3 | import com.github.hellxz.oauth2.dao.ClientUserRepositories;
4 | import com.github.hellxz.oauth2.domain.ClientUser;
5 | import org.springframework.beans.factory.annotation.Autowired;
6 | import org.springframework.security.core.userdetails.UserDetails;
7 | import org.springframework.security.core.userdetails.UserDetailsService;
8 | import org.springframework.security.core.userdetails.UsernameNotFoundException;
9 | import org.springframework.security.crypto.password.PasswordEncoder;
10 | import org.springframework.stereotype.Service;
11 |
12 | import java.util.Objects;
13 |
14 | @Service
15 | public class ClientUserDetailsService implements UserDetailsService {
16 |
17 | @Autowired
18 | private ClientUserRepositories clientUserRepositories;
19 |
20 | @Autowired
21 | private PasswordEncoder passwordEncoder;
22 |
23 | /**
24 | * 数据库查用户对象实现,这里不做权限控制
25 | */
26 | @Override
27 | public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
28 | ClientUser clientUser = clientUserRepositories.findOneByUsername(username);
29 | if(Objects.isNull(clientUser)){
30 | throw new UsernameNotFoundException("用户不存在");
31 | }
32 | return clientUser;
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/authorization-code/authorization-code-client-resttemplate-jdbc/src/main/java/com/github/hellxz/oauth2/config/OAuth2ClientProperties.java:
--------------------------------------------------------------------------------
1 | package com.github.hellxz.oauth2.config;
2 |
3 | import org.apache.commons.lang3.builder.ToStringBuilder;
4 | import org.apache.commons.lang3.builder.ToStringStyle;
5 | import org.slf4j.Logger;
6 | import org.slf4j.LoggerFactory;
7 | import org.springframework.boot.context.properties.ConfigurationProperties;
8 | import org.springframework.stereotype.Component;
9 |
10 | import javax.annotation.PostConstruct;
11 |
12 | @Component
13 | @ConfigurationProperties(prefix = "oauth2.client")
14 | public class OAuth2ClientProperties {
15 |
16 | private static final Logger log = LoggerFactory.getLogger(OAuth2ClientProperties.class);
17 |
18 | private String clientId;
19 | private String clientSecret;
20 | private String redirectUri;
21 | private String responseType;
22 | private String scope;
23 |
24 | @PostConstruct
25 | public void outputProperties(){
26 | log.info("当前OAuth2客户端配置:{}", this);
27 | }
28 |
29 | public String getClientId() {
30 | return clientId;
31 | }
32 |
33 | public void setClientId(String clientId) {
34 | this.clientId = clientId;
35 | }
36 |
37 | public String getClientSecret() {
38 | return clientSecret;
39 | }
40 |
41 | public void setClientSecret(String clientSecret) {
42 | this.clientSecret = clientSecret;
43 | }
44 |
45 | public String getRedirectUri() {
46 | return redirectUri;
47 | }
48 |
49 | public void setRedirectUri(String redirectUri) {
50 | this.redirectUri = redirectUri;
51 | }
52 |
53 | public String getResponseType() {
54 | return responseType;
55 | }
56 |
57 | public void setResponseType(String responseType) {
58 | this.responseType = responseType;
59 | }
60 |
61 | public String getScope() {
62 | return scope;
63 | }
64 |
65 | public void setScope(String scope) {
66 | this.scope = scope;
67 | }
68 |
69 | @Override
70 | public String toString() {
71 | return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE);
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/authorization-code/authorization-code-client-resttemplate-jdbc/src/main/java/com/github/hellxz/oauth2/config/OAuth2ServerProperties.java:
--------------------------------------------------------------------------------
1 | package com.github.hellxz.oauth2.config;
2 |
3 | import org.apache.commons.lang3.builder.ToStringBuilder;
4 | import org.apache.commons.lang3.builder.ToStringStyle;
5 | import org.slf4j.Logger;
6 | import org.slf4j.LoggerFactory;
7 | import org.springframework.boot.context.properties.ConfigurationProperties;
8 | import org.springframework.stereotype.Component;
9 |
10 | import javax.annotation.PostConstruct;
11 |
12 | @Component
13 | @ConfigurationProperties(prefix = "oauth2.server")
14 | public class OAuth2ServerProperties {
15 |
16 | private static final Logger log = LoggerFactory.getLogger(OAuth2ServerProperties.class);
17 |
18 | private String host;
19 | private String authorizeUrl;
20 | private String tokenUrl;
21 | private String checkTokenUrl;
22 |
23 | @PostConstruct
24 | public void outputProperties(){
25 | log.info("当前OAuth2服务端配置:{}", this);
26 | }
27 |
28 | public String getHost() {
29 | return host;
30 | }
31 |
32 | public void setHost(String host) {
33 | this.host = host;
34 | }
35 |
36 | public String getAuthorizeUrl() {
37 | return authorizeUrl;
38 | }
39 |
40 | public void setAuthorizeUrl(String authorizeUrl) {
41 | this.authorizeUrl = authorizeUrl;
42 | }
43 |
44 | public String getTokenUrl() {
45 | return tokenUrl;
46 | }
47 |
48 | public void setTokenUrl(String tokenUrl) {
49 | this.tokenUrl = tokenUrl;
50 | }
51 |
52 | public String getCheckTokenUrl() {
53 | return checkTokenUrl;
54 | }
55 |
56 | public void setCheckTokenUrl(String checkTokenUrl) {
57 | this.checkTokenUrl = checkTokenUrl;
58 | }
59 |
60 | @Override
61 | public String toString() {
62 | return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE);
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/authorization-code/authorization-code-client-resttemplate-jdbc/src/main/java/com/github/hellxz/oauth2/config/SecurityConfig.java:
--------------------------------------------------------------------------------
1 | package com.github.hellxz.oauth2.config;
2 |
3 | import com.github.hellxz.oauth2.dao.ClientUserRepositories;
4 | import org.springframework.beans.factory.annotation.Autowired;
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.annotation.authentication.builders.AuthenticationManagerBuilder;
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.configuration.WebSecurityConfigurerAdapter;
12 | import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
13 | import org.springframework.security.crypto.password.PasswordEncoder;
14 |
15 | import javax.sql.DataSource;
16 |
17 | @Configuration
18 | @EnableWebSecurity
19 | public class SecurityConfig extends WebSecurityConfigurerAdapter {
20 |
21 | @Bean
22 | public PasswordEncoder passwordEncoder() {
23 | return new BCryptPasswordEncoder();
24 | }
25 | @Autowired
26 | private ClientUserRepositories clientUserRepositories;
27 |
28 | @Autowired
29 | private ClientUserDetailsService clientUserDetailsService;
30 |
31 | @Autowired
32 | private DataSource dataSource;
33 |
34 | @Override
35 | protected void configure(HttpSecurity http) throws Exception {
36 | //@formatter:off
37 | http.authorizeRequests()
38 | //仅放通登录接口
39 | .antMatchers(HttpMethod.GET, "/", "/index", "/api/login", "/callback").permitAll()
40 | .anyRequest().authenticated()
41 | .and()
42 | .httpBasic();
43 | //@formatter:on
44 | }
45 |
46 | @Override
47 | protected void configure(AuthenticationManagerBuilder auth) throws Exception {
48 | auth.userDetailsService(clientUserDetailsService);
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/authorization-code/authorization-code-client-resttemplate-jdbc/src/main/java/com/github/hellxz/oauth2/consts/GrantType.java:
--------------------------------------------------------------------------------
1 | package com.github.hellxz.oauth2.consts;
2 |
3 | public enum GrantType {
4 | /**
5 | * 授权码
6 | */
7 | AUTHORIZATION_CODE("authorization_code"),
8 | /**
9 | * 简化模式
10 | */
11 | IMPLICIT("implicit"),
12 | /**
13 | * 客户端模式
14 | */
15 | CLIENT_CREDENTIALS("client_credentials"),
16 | /**
17 | * 用户密码模式
18 | */
19 | PASSWORD("password");
20 |
21 | private String code;
22 | GrantType(String code){
23 | this.code = code;
24 | }
25 |
26 | public String getCode() {
27 | return code;
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/authorization-code/authorization-code-client-resttemplate-jdbc/src/main/java/com/github/hellxz/oauth2/dao/ClientUserRepositories.java:
--------------------------------------------------------------------------------
1 | package com.github.hellxz.oauth2.dao;
2 |
3 | import com.github.hellxz.oauth2.domain.ClientUser;
4 | import org.springframework.data.jpa.repository.JpaRepository;
5 |
6 | public interface ClientUserRepositories extends JpaRepository {
7 | ClientUser findOneByUsername(String username);
8 | }
9 |
--------------------------------------------------------------------------------
/authorization-code/authorization-code-client-resttemplate-jdbc/src/main/java/com/github/hellxz/oauth2/domain/ClientUser.java:
--------------------------------------------------------------------------------
1 | package com.github.hellxz.oauth2.domain;
2 |
3 | import org.apache.commons.lang3.builder.ToStringBuilder;
4 | import org.apache.commons.lang3.builder.ToStringStyle;
5 | import org.springframework.security.core.GrantedAuthority;
6 | import org.springframework.security.core.userdetails.UserDetails;
7 |
8 | import javax.persistence.Column;
9 | import javax.persistence.Entity;
10 | import javax.persistence.GeneratedValue;
11 | import javax.persistence.Id;
12 | import java.io.Serializable;
13 | import java.util.Calendar;
14 | import java.util.Collection;
15 | import java.util.Collections;
16 |
17 | @Entity(name = "client_user")
18 | public class ClientUser implements UserDetails, Serializable {
19 |
20 | private static final long serialVersionUID = 1L;
21 |
22 | @Id
23 | @GeneratedValue
24 | @Column(name = "id")
25 | private long id;
26 | @Column(name = "username")
27 | private String username;
28 | @Column(name = "password")
29 | private String password;
30 | @Column(name = "access_token")
31 | private String accessToken;
32 | @Column(name = "refresh_token")
33 | private String refreshToken;
34 | @Column(name = "validate_token_expire")
35 | private Calendar validateTokenExpire;
36 |
37 | public long getId() {
38 | return id;
39 | }
40 |
41 | public void setId(long id) {
42 | this.id = id;
43 | }
44 |
45 | public String getUsername() {
46 | return username;
47 | }
48 |
49 | @Override
50 | public boolean isAccountNonExpired() {
51 | return true;
52 | }
53 |
54 | @Override
55 | public boolean isAccountNonLocked() {
56 | return true;
57 | }
58 |
59 | @Override
60 | public boolean isCredentialsNonExpired() {
61 | return true;
62 | }
63 |
64 | @Override
65 | public boolean isEnabled() {
66 | return true;
67 | }
68 |
69 | public void setUsername(String username) {
70 | this.username = username;
71 | }
72 |
73 | @Override
74 | public Collection extends GrantedAuthority> getAuthorities() {
75 | return Collections.emptyList();
76 | }
77 |
78 | public String getPassword() {
79 | return password;
80 | }
81 |
82 | public void setPassword(String password) {
83 | this.password = password;
84 | }
85 |
86 | public String getAccessToken() {
87 | return accessToken;
88 | }
89 |
90 | public void setAccessToken(String accessToken) {
91 | this.accessToken = accessToken;
92 | }
93 |
94 | public String getRefreshToken() {
95 | return refreshToken;
96 | }
97 |
98 | public void setRefreshToken(String refreshToken) {
99 | this.refreshToken = refreshToken;
100 | }
101 |
102 | public Calendar getValidateTokenExpire() {
103 | return validateTokenExpire;
104 | }
105 |
106 | public void setValidateTokenExpire(Calendar validateTokenExpire) {
107 | this.validateTokenExpire = validateTokenExpire;
108 | }
109 |
110 | @Override
111 | public String toString() {
112 | return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE);
113 | }
114 | }
115 |
--------------------------------------------------------------------------------
/authorization-code/authorization-code-client-resttemplate-jdbc/src/main/java/com/github/hellxz/oauth2/dto/TokenDTO.java:
--------------------------------------------------------------------------------
1 | package com.github.hellxz.oauth2.dto;
2 |
3 | import com.fasterxml.jackson.annotation.JsonProperty;
4 | import org.apache.commons.lang3.builder.ToStringBuilder;
5 | import org.apache.commons.lang3.builder.ToStringStyle;
6 |
7 | /**
8 | * 授权成功token返回体
9 | */
10 | public class TokenDTO {
11 | @JsonProperty("access_token")
12 | private String accessToken;
13 | @JsonProperty("refresh_token")
14 | private String refreshToken;
15 | @JsonProperty("token_type")
16 | private String tokenType;
17 | @JsonProperty("expires_in")
18 | private String expiresIn;
19 | @JsonProperty("scope")
20 | private String scope;
21 |
22 | public String getRefreshToken() {
23 | return refreshToken;
24 | }
25 |
26 | public void setRefreshToken(String refreshToken) {
27 | this.refreshToken = refreshToken;
28 | }
29 |
30 | public String getAccessToken() {
31 | return accessToken;
32 | }
33 |
34 | public void setAccessToken(String accessToken) {
35 | this.accessToken = accessToken;
36 | }
37 |
38 | public String getTokenType() {
39 | return tokenType;
40 | }
41 |
42 | public void setTokenType(String tokenType) {
43 | this.tokenType = tokenType;
44 | }
45 |
46 | public String getExpiresIn() {
47 | return expiresIn;
48 | }
49 |
50 | public void setExpiresIn(String expiresIn) {
51 | this.expiresIn = expiresIn;
52 | }
53 |
54 | public String getScope() {
55 | return scope;
56 | }
57 |
58 | public void setScope(String scope) {
59 | this.scope = scope;
60 | }
61 |
62 | @Override
63 | public String toString() {
64 | return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE);
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/authorization-code/authorization-code-client-resttemplate-jdbc/src/main/java/com/github/hellxz/oauth2/service/ClientUserService.java:
--------------------------------------------------------------------------------
1 | package com.github.hellxz.oauth2.service;
2 |
3 | import com.github.hellxz.oauth2.dao.ClientUserRepositories;
4 | import com.github.hellxz.oauth2.domain.ClientUser;
5 | import com.github.hellxz.oauth2.utils.SecurityUtils;
6 | import org.springframework.beans.factory.annotation.Autowired;
7 | import org.springframework.stereotype.Service;
8 |
9 | import java.util.Optional;
10 |
11 | @Service
12 | public class ClientUserService {
13 |
14 | @Autowired
15 | private ClientUserRepositories repositories;
16 |
17 | public void updateClientUser(ClientUser clientUser){
18 | Optional userById = repositories.findById(clientUser.getId());
19 | if(userById.isPresent()){
20 | repositories.save(clientUser);
21 | }
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/authorization-code/authorization-code-client-resttemplate-jdbc/src/main/java/com/github/hellxz/oauth2/service/TokenService.java:
--------------------------------------------------------------------------------
1 | package com.github.hellxz.oauth2.service;
2 |
3 | import com.github.hellxz.oauth2.config.OAuth2ClientProperties;
4 | import com.github.hellxz.oauth2.config.OAuth2ServerProperties;
5 | import com.github.hellxz.oauth2.consts.GrantType;
6 | import com.github.hellxz.oauth2.domain.ClientUser;
7 | import com.github.hellxz.oauth2.dto.TokenDTO;
8 | import com.github.hellxz.oauth2.web.vo.UserInfo;
9 | import org.springframework.beans.factory.annotation.Autowired;
10 | import org.springframework.http.*;
11 | import org.springframework.stereotype.Component;
12 | import org.springframework.util.LinkedMultiValueMap;
13 | import org.springframework.util.MultiValueMap;
14 | import org.springframework.web.client.HttpClientErrorException;
15 | import org.springframework.web.client.RestTemplate;
16 | import org.springframework.web.servlet.ModelAndView;
17 |
18 | import java.io.UnsupportedEncodingException;
19 | import java.net.URI;
20 | import java.net.URLEncoder;
21 | import java.util.*;
22 |
23 | @Component
24 | public class TokenService {
25 |
26 | @Autowired
27 | private OAuth2ServerProperties auth2ServerProperties;
28 |
29 | @Autowired
30 | private OAuth2ClientProperties auth2ClientProperties;
31 |
32 | @Autowired
33 | private RestTemplate restTemplate;
34 |
35 | /**
36 | * 请求授权码url
37 | */
38 | public String getAuthorizeUrl() {
39 | HashMap params = new HashMap<>();
40 | params.put("client_id", auth2ClientProperties.getClientId());
41 | params.put("redirect_uri", URLEncoder.encode(auth2ClientProperties.getRedirectUri()));
42 | params.put("response_type", auth2ClientProperties.getResponseType());
43 | params.put("scope", URLEncoder.encode(auth2ClientProperties.getScope()));
44 | return buildUrlStr(auth2ServerProperties.getAuthorizeUrl(), params);
45 | }
46 |
47 | /**
48 | * 请求授权token的url
49 | */
50 | public String getToken(String code) throws UnsupportedEncodingException {
51 | RequestEntity httpEntity = new RequestEntity<>(getHttpBody(code), getHttpHeaders(), HttpMethod.POST, URI.create(auth2ServerProperties.getTokenUrl()));
52 | ResponseEntity exchange = restTemplate.exchange(httpEntity, TokenDTO.class);
53 | if (exchange.getStatusCode().is2xxSuccessful()) {
54 | System.err.println(exchange.getBody());
55 | return Objects.requireNonNull(exchange.getBody()).getAccessToken();
56 | }
57 | throw new RuntimeException("请求令牌失败!");
58 | }
59 |
60 | public void tryGetUserInfo(ModelAndView mv, ClientUser currentUser) {
61 | //正常请求资源服务器,获取用户信息
62 | HttpHeaders headers = new HttpHeaders();
63 | headers.setBearerAuth(currentUser.getAccessToken());
64 | RequestEntity> requestEntity
65 | = new RequestEntity<>(headers, HttpMethod.GET, URI.create("http://localhost:8081/user/jack"));
66 | ResponseEntity exchange = null;
67 | try{
68 | //尝试访问资源
69 | exchange = restTemplate.exchange(requestEntity, UserInfo.class);
70 | }catch (HttpClientErrorException exception){
71 | //未认证会报错,重定向到授权页面,获取新token
72 | mv.setViewName("redirect:" + getAuthorizeUrl());
73 | return;
74 | }
75 | assert exchange != null;
76 | if (exchange.getStatusCode().is2xxSuccessful()) {
77 | UserInfo body = exchange.getBody();
78 | mv.addObject("currentLoginUsername", currentUser.getUsername());
79 | mv.addObject("user", body);
80 | }
81 | }
82 |
83 | private HttpHeaders getHttpHeaders() {
84 | HttpHeaders httpHeaders = new HttpHeaders();
85 | httpHeaders.setBasicAuth(auth2ClientProperties.getClientId(), auth2ClientProperties.getClientSecret());
86 | httpHeaders.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
87 | httpHeaders.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));
88 | return httpHeaders;
89 | }
90 |
91 | private MultiValueMap getHttpBody(String code) throws UnsupportedEncodingException {
92 | MultiValueMap params = new LinkedMultiValueMap<>();
93 | params.add("code", code);
94 | params.add("grant_type", GrantType.AUTHORIZATION_CODE.getCode());
95 | params.add("redirect_uri", auth2ClientProperties.getRedirectUri());
96 | params.add("scope", auth2ClientProperties.getScope());
97 | return params;
98 | }
99 |
100 | /**
101 | * 构建url
102 | *
103 | * @param endpoint 服务器端点url
104 | * @param params 参数列表
105 | * @return 带参数的url
106 | */
107 | private String buildUrlStr(String endpoint, Map params) {
108 | List keyValueParam = new ArrayList<>(params.size());
109 | params.forEach((key, value) -> keyValueParam.add(key + "=" + value));
110 | return endpoint + "?" + keyValueParam.stream().reduce((a, b) -> a + "&" + b).get();
111 | }
112 | }
113 |
--------------------------------------------------------------------------------
/authorization-code/authorization-code-client-resttemplate-jdbc/src/main/java/com/github/hellxz/oauth2/utils/SecurityUtils.java:
--------------------------------------------------------------------------------
1 | package com.github.hellxz.oauth2.utils;
2 |
3 | import com.github.hellxz.oauth2.domain.ClientUser;
4 | import com.github.hellxz.oauth2.service.ClientUserService;
5 | import org.springframework.beans.factory.annotation.Autowired;
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.core.userdetails.UserDetails;
10 | import org.springframework.stereotype.Component;
11 |
12 | @Component
13 | public class SecurityUtils {
14 |
15 | @Autowired
16 | private ClientUserService clientUserService;
17 |
18 | public UserDetails getCurrentUser(){
19 | SecurityContext context = SecurityContextHolder.getContext();
20 | Authentication authentication = context.getAuthentication();
21 | Object principal = authentication.getPrincipal();
22 | if(principal instanceof UserDetails){
23 | return (UserDetails) principal;
24 | }
25 | return null;
26 | }
27 |
28 | /**
29 | * 更新token
30 | */
31 | public void updateToken(String token){
32 | SecurityContext context = SecurityContextHolder.getContext();
33 | Authentication authentication = context.getAuthentication();
34 | Object principal = authentication.getPrincipal();
35 | if(principal instanceof ClientUser){
36 | ClientUser clientUser = (ClientUser) principal;
37 | clientUser.setAccessToken(token);
38 | clientUserService.updateClientUser(clientUser);
39 | }
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/authorization-code/authorization-code-client-resttemplate-jdbc/src/main/java/com/github/hellxz/oauth2/web/MainPageController.java:
--------------------------------------------------------------------------------
1 | package com.github.hellxz.oauth2.web;
2 |
3 | import com.github.hellxz.oauth2.domain.ClientUser;
4 | import com.github.hellxz.oauth2.service.TokenService;
5 | import com.github.hellxz.oauth2.utils.SecurityUtils;
6 | import org.apache.commons.lang3.StringUtils;
7 | import org.springframework.beans.factory.annotation.Autowired;
8 | import org.springframework.stereotype.Controller;
9 | import org.springframework.web.bind.annotation.GetMapping;
10 | import org.springframework.web.bind.annotation.RequestParam;
11 | import org.springframework.web.client.RestTemplate;
12 | import org.springframework.web.servlet.ModelAndView;
13 |
14 | import java.io.UnsupportedEncodingException;
15 |
16 | /**
17 | * 页面控制器,本示例中所有controller都在这里
18 | */
19 | @Controller
20 | public class MainPageController {
21 |
22 | @Autowired
23 | private RestTemplate restTemplate;
24 |
25 | @Autowired
26 | private TokenService tokenService;
27 |
28 | @Autowired
29 | private SecurityUtils securityUtils;
30 |
31 | /**
32 | * 主页
33 | */
34 | @GetMapping(value = {"/", "/index"})
35 | public String index(){
36 | return "index";
37 | }
38 |
39 | /**
40 | * 回调
41 | */
42 | @GetMapping("/callback")
43 | public ModelAndView callback(@RequestParam("code") String code) throws UnsupportedEncodingException {
44 | String token = tokenService.getToken(code);
45 | if(StringUtils.isNotBlank(token)){
46 | securityUtils.updateToken(token);
47 | return new ModelAndView("redirect:/user-info");
48 | }
49 | throw new RuntimeException("请求超时");
50 | }
51 |
52 | /**
53 | * 用于测试获取token与访问资源服务器资源的功能
54 | */
55 | @GetMapping("/user-info")
56 | public ModelAndView userInfoPage(){
57 | //获取当前登录的用户,这个用户对象中包含数据库中保存的token
58 | ClientUser currentUser = (ClientUser)securityUtils.getCurrentUser();
59 | //不存在需要去走一次授权码模式流程
60 | if(null != currentUser && StringUtils.isBlank(currentUser.getAccessToken())){
61 | //重定向到授权服务器进行授权, 先获取授权码
62 | return new ModelAndView("redirect:"+tokenService.getAuthorizeUrl());
63 | }
64 | ModelAndView modelAndView = new ModelAndView("user-info");
65 | //尝试获取资源
66 | tokenService.tryGetUserInfo(modelAndView, currentUser);
67 | return modelAndView;
68 | }
69 |
70 | }
71 |
--------------------------------------------------------------------------------
/authorization-code/authorization-code-client-resttemplate-jdbc/src/main/java/com/github/hellxz/oauth2/web/vo/UserInfo.java:
--------------------------------------------------------------------------------
1 | package com.github.hellxz.oauth2.web.vo;
2 |
3 | import com.fasterxml.jackson.annotation.JsonProperty;
4 | import org.apache.commons.lang3.builder.ToStringBuilder;
5 | import org.apache.commons.lang3.builder.ToStringStyle;
6 |
7 | public class UserInfo {
8 | @JsonProperty("username")
9 | private String username;
10 | @JsonProperty("email")
11 | private String email;
12 |
13 | public String getEmail() {
14 | return email;
15 | }
16 |
17 | public void setEmail(String email) {
18 | this.email = email;
19 | }
20 |
21 | public String getUsername() {
22 | return username;
23 | }
24 |
25 | public void setUsername(String username) {
26 | this.username = username;
27 | }
28 |
29 | @Override
30 | public String toString() {
31 | return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE);
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/authorization-code/authorization-code-client-resttemplate-jdbc/src/main/resources/application.yml:
--------------------------------------------------------------------------------
1 | server:
2 | port: 9001
3 |
4 | spring:
5 | http:
6 | converters:
7 | preferred-json-mapper: jackson
8 | thymeleaf:
9 | cache: false
10 | datasource:
11 | driver-class-name: com.mysql.cj.jdbc.Driver
12 | url: jdbc:mysql://localhost:3306/oauth2_client_db?useSSL=false&useCharacterEncoding=utf-8
13 | username: root
14 | password: root
15 | jpa:
16 | properties:
17 | hibernate:
18 | hbm2ddl.auto: update
19 | dialect: org.hibernate.dialect.MySQL5InnoDBDialect
20 | show-sql: true
21 |
22 | oauth2:
23 | client:
24 | client-id: client-a
25 | client-secret: client-a-secret
26 | redirect_uri: http://localhost:${server.port}/callback
27 | response_type: code
28 | scope: read_user_info
29 | server:
30 | host: http://localhost:8080
31 | authorize-url: ${oauth2.server.host}/oauth/authorize
32 | token-url: ${oauth2.server.host}/oauth/token
33 | check-token-url: ${oauth2.server.host}/oauth/check_token
34 |
--------------------------------------------------------------------------------
/authorization-code/authorization-code-client-resttemplate-jdbc/src/main/resources/sql/create_table.sql:
--------------------------------------------------------------------------------
1 | -- 创建数据库
2 | create database if not exists `oauth2_client_db` default character set utf8 collate utf8_general_ci;
3 | use oauth2_client_db;
4 | -- 创建client端用户,这里可以与授权服务登录用户名和密码不一致
5 | create table if not exists client_user
6 | (
7 | id bigint auto_increment primary key,
8 | username varchar(32) not null,
9 | `password` varchar(64) not null,
10 | access_token varchar(256) default null,
11 | validate_token_expire datetime,
12 | refresh_token varchar(256) default null
13 | );
14 | -- 每次启动清空上次用户表,仅用于测试
15 | truncate table client_user;
16 | -- 插入一个与授权服务器密码不一致的用户
17 | insert into client_user values (null,'hellxz','$2a$10$iAEfWxvrLKt6bhBdkNsdCeMn6JEqrS8c6MF/pbbeAeCxVrgkH92Re', null, null, null);
18 |
--------------------------------------------------------------------------------
/authorization-code/authorization-code-client-resttemplate-jdbc/src/main/resources/templates/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | 首页
6 |
7 |
8 | 点此进入用户详情页
9 |
10 |
--------------------------------------------------------------------------------
/authorization-code/authorization-code-client-resttemplate-jdbc/src/main/resources/templates/user-info.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | 用户详情页面
6 |
7 |
8 | 当前登录的用户为:
test
9 |
10 |
11 | 获得的用户信息为:
12 |
13 | - 用户名:测试用户
14 | - 密码:测试email
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/authorization-code/authorization-code-client-resttemplate-jdbc/src/test/java/com/github/hellxz/oauth2/ClientUserTests.java:
--------------------------------------------------------------------------------
1 | package com.github.hellxz.oauth2;
2 |
3 | import com.github.hellxz.oauth2.dao.ClientUserRepositories;
4 | import com.github.hellxz.oauth2.domain.ClientUser;
5 | import org.junit.Assert;
6 | import org.junit.Before;
7 | import org.junit.Test;
8 | import org.junit.runner.RunWith;
9 | import org.springframework.beans.factory.annotation.Autowired;
10 | import org.springframework.boot.test.context.SpringBootTest;
11 | import org.springframework.security.crypto.password.PasswordEncoder;
12 | import org.springframework.test.context.junit4.SpringRunner;
13 | import org.springframework.test.web.servlet.MockMvc;
14 | import org.springframework.test.web.servlet.setup.MockMvcBuilders;
15 | import org.springframework.web.context.WebApplicationContext;
16 |
17 | import javax.transaction.Transactional;
18 | import java.util.Calendar;
19 | import java.util.Date;
20 |
21 | @RunWith(SpringRunner.class)
22 | @SpringBootTest(classes = AuthorizationCodeClientApp.class)
23 | public class ClientUserTests {
24 |
25 | @Autowired
26 | private WebApplicationContext webApplicationContext;
27 | @Autowired
28 | private PasswordEncoder passwordEncoder;
29 | private MockMvc mockMvc;
30 | @Autowired
31 | private ClientUserRepositories clientUserRepositories;
32 |
33 | @Before
34 | public void init(){
35 | mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
36 | }
37 |
38 | @Test
39 | @Transactional
40 | public void insertClientUserTest(){
41 | ClientUser user = new ClientUser();
42 | user.setUsername("刺客五六七");
43 | user.setPassword("567");
44 | user.setAccessToken("test");
45 | user.setRefreshToken("test");
46 | Calendar calendar = Calendar.getInstance();
47 | calendar.setTime(new Date(System.currentTimeMillis() + 100000000L));
48 | user.setValidateTokenExpire(calendar);
49 | ClientUser save = clientUserRepositories.save(user);
50 | Assert.assertNotNull(save);
51 | Assert.assertEquals(user.getUsername(), save.getUsername());
52 | Assert.assertEquals(user.getPassword(), save.getPassword());
53 | }
54 | @Test
55 | public void insertClientUserTest2(){
56 | ClientUser user = new ClientUser();
57 | user.setUsername("hellxz");
58 | user.setPassword(passwordEncoder.encode("abc"));
59 | ClientUser save = clientUserRepositories.save(user);
60 | Assert.assertNotNull(save);
61 | Assert.assertEquals(user.getUsername(), save.getUsername());
62 | Assert.assertEquals(user.getPassword(), save.getPassword());
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/authorization-code/authorization-code-resource-server/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 | authorization-code
7 | com.github.hellxz
8 | 0.0.1-SNAPSHOT
9 |
10 | 4.0.0
11 |
12 | authorization-code-resource-server
13 |
--------------------------------------------------------------------------------
/authorization-code/authorization-code-resource-server/src/main/java/com/github/hellxz/oauth2/AuthorizationCodeResourceServerApp.java:
--------------------------------------------------------------------------------
1 | package com.github.hellxz.oauth2;
2 |
3 | import org.springframework.boot.SpringApplication;
4 | import org.springframework.boot.autoconfigure.SpringBootApplication;
5 |
6 | /**
7 | * 资源服务器 入口
8 | *
9 | * @author hellxz
10 | */
11 | @SpringBootApplication
12 | public class AuthorizationCodeResourceServerApp {
13 |
14 | public static void main(String[] args) {
15 | SpringApplication.run(AuthorizationCodeResourceServerApp.class, args);
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/authorization-code/authorization-code-resource-server/src/main/java/com/github/hellxz/oauth2/config/ResourceConfig.java:
--------------------------------------------------------------------------------
1 | package com.github.hellxz.oauth2.config;
2 |
3 | import org.springframework.context.annotation.Bean;
4 | import org.springframework.context.annotation.Configuration;
5 | import org.springframework.context.annotation.Primary;
6 | import org.springframework.security.config.annotation.web.builders.HttpSecurity;
7 | import org.springframework.security.config.http.SessionCreationPolicy;
8 | import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
9 | import org.springframework.security.crypto.password.PasswordEncoder;
10 | import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
11 | import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
12 | import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer;
13 | import org.springframework.security.oauth2.provider.token.RemoteTokenServices;
14 |
15 | @Configuration
16 | @EnableResourceServer
17 | public class ResourceConfig extends ResourceServerConfigurerAdapter {
18 |
19 | @Bean
20 | public PasswordEncoder passwordEncoder() {
21 | return new BCryptPasswordEncoder();
22 | }
23 |
24 | @Primary
25 | @Bean
26 | public RemoteTokenServices remoteTokenServices() {
27 | final RemoteTokenServices tokenServices = new RemoteTokenServices();
28 | //设置授权服务器check_token端点完整地址
29 | tokenServices.setCheckTokenEndpointUrl("http://localhost:8080/oauth/check_token");
30 | //设置客户端id与secret,注意:client_secret值不能使用passwordEncoder加密!
31 | tokenServices.setClientId("client-a");
32 | tokenServices.setClientSecret("client-a-secret");
33 | return tokenServices;
34 | }
35 |
36 | @Override
37 | public void configure(HttpSecurity http) throws Exception {
38 | //设置创建session策略
39 | http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED);
40 | //@formatter:off
41 | //所有请求必须授权
42 | http.authorizeRequests()
43 | .anyRequest().authenticated();
44 | //@formatter:on
45 | }
46 |
47 | @Override
48 | public void configure(ResourceServerSecurityConfigurer resources) {
49 | resources.resourceId("resource1").stateless(true);
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/authorization-code/authorization-code-resource-server/src/main/java/com/github/hellxz/oauth2/web/controller/ResourceController.java:
--------------------------------------------------------------------------------
1 | package com.github.hellxz.oauth2.web.controller;
2 |
3 | import com.github.hellxz.oauth2.web.vo.UserVO;
4 | import org.springframework.web.bind.annotation.GetMapping;
5 | import org.springframework.web.bind.annotation.PathVariable;
6 | import org.springframework.web.bind.annotation.RestController;
7 |
8 | @RestController
9 | public class ResourceController {
10 |
11 | @GetMapping("/user/{username}")
12 | public UserVO user(@PathVariable String username){
13 | return new UserVO(username, username + "@foxmail.com");
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/authorization-code/authorization-code-resource-server/src/main/java/com/github/hellxz/oauth2/web/vo/UserVO.java:
--------------------------------------------------------------------------------
1 | package com.github.hellxz.oauth2.web.vo;
2 |
3 | public class UserVO {
4 | private String username;
5 | private String email;
6 |
7 | public UserVO(String username, String email) {
8 | this.username = username;
9 | this.email = email;
10 | }
11 |
12 | public String getUsername() {
13 | return username;
14 | }
15 |
16 | public void setUsername(String username) {
17 | this.username = username;
18 | }
19 |
20 | public String getEmail() {
21 | return email;
22 | }
23 |
24 | public void setEmail(String email) {
25 | this.email = email;
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/authorization-code/authorization-code-resource-server/src/main/resources/application.properties:
--------------------------------------------------------------------------------
1 | server.port=8081
--------------------------------------------------------------------------------
/authorization-code/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 | spring-security-oauth2-learn
7 | com.github.hellxz
8 | 0.0.1-SNAPSHOT
9 |
10 | 4.0.0
11 |
12 | authorization-code
13 | pom
14 |
15 | authorization-code-authorization-server
16 | authorization-code-resource-server
17 | authorization-code-client-resttemplate-jdbc
18 |
19 |
20 |
21 |
22 | org.springframework.security.oauth
23 | spring-security-oauth2
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/client-credentials/README.md:
--------------------------------------------------------------------------------
1 | ## 客户端模式DEMO
2 | 以下是我的理解:
3 | 当用户发起一个访问资源服务的请求前,被客户端(浏览器)拦截到,它会先检查本地是否有token,
4 |
5 | 如果token不存在就先发起一次Post请求,用自己的客户端账号密码获取token,
6 |
7 | 然后使用此token添加到之前拦截到的请求头中,执行请求,返回资源
8 |
9 | **关键点在于:这里没有用户登录与授权的部分,实际相对授权服务器登录的是客户端**
10 |
11 | 1. 发起请求,登录授权服务器获取token
12 | ```
13 | curl -X POST \
14 | --user user-center:12345 http://localhost:8080/oauth/token \
15 | -d "grant_type=client_credentials&scope=all"
16 | ```
17 |
18 | 返回响应
19 | ```json
20 | {
21 | "access_token": "fc4721f4-c4a3-44f8-8232-a31cf59964ca",
22 | "token_type": "bearer",
23 | "expires_in": 43199,
24 | "scope": "all"
25 | }
26 | ```
27 | 2. 调用资源接口
28 | ```
29 | curl -X GET --user user-center:12345 http://localhost:8081/user/hellxz001
30 | -H 'Authorization: Bearer fc4721f4-c4a3-44f8-8232-a31cf59964ca'
31 | ```
32 | 返回响应
33 | ```json
34 | {
35 | "username": "hellxz001",
36 | "email": "hellxz001@foxmail.com"
37 | }
38 | ```
39 |
40 | ## 校验token
41 | 另外,我这边尝试了一下校验token的接口,之前使用授权码等校验时,只需要传token、client_id、client_secret
42 | 就可以正确校验token,
43 |
44 | 如果是client_credentials模式,校验接口时,需要使用client_id、client_secret登录,传参时只需要传token
45 |
46 | ```
47 | curl -X POST --user user-center:12345 http://localhost:8080/oauth/check_token \
48 | -d 'token=b462bd1f-a50c-4209-ac06-5a668143ed9e'
49 | ```
50 | 返回结果
51 | ```json
52 | {
53 | "scope": [
54 | "all"
55 | ],
56 | "active": true,
57 | "exp": 1574889562,
58 | "client_id": "user-center"
59 | }
60 | ```
--------------------------------------------------------------------------------
/client-credentials/client-credentials-authorization-server/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 | client-credentials
7 | com.github.hellxz
8 | 0.0.1-SNAPSHOT
9 |
10 | 4.0.0
11 |
12 | client-credentials-authorization-server
13 |
--------------------------------------------------------------------------------
/client-credentials/client-credentials-authorization-server/src/main/java/com/github/hellxz/oauth2/ClientCredentialsAuthorizationApp.java:
--------------------------------------------------------------------------------
1 | package com.github.hellxz.oauth2;
2 |
3 | import org.springframework.boot.SpringApplication;
4 | import org.springframework.boot.autoconfigure.SpringBootApplication;
5 |
6 | @SpringBootApplication
7 | public class ClientCredentialsAuthorizationApp {
8 | public static void main(String[] args) {
9 | SpringApplication.run(ClientCredentialsAuthorizationApp.class, args);
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/client-credentials/client-credentials-authorization-server/src/main/java/com/github/hellxz/oauth2/config/AuthorizationConfig.java:
--------------------------------------------------------------------------------
1 | package com.github.hellxz.oauth2.config;
2 |
3 | import org.springframework.context.annotation.Bean;
4 | import org.springframework.context.annotation.Configuration;
5 | import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
6 | import org.springframework.security.crypto.password.PasswordEncoder;
7 | import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
8 | import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
9 | import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
10 | import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
11 |
12 | @Configuration
13 | @EnableAuthorizationServer
14 | public class AuthorizationConfig extends AuthorizationServerConfigurerAdapter {
15 | @Bean
16 | public PasswordEncoder passwordEncoder(){
17 | return new BCryptPasswordEncoder();
18 | }
19 |
20 | @Override
21 | public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
22 | //@formatter:off
23 | clients.inMemory()
24 | .withClient("user-center")
25 | .secret(passwordEncoder().encode("12345"))
26 | .authorizedGrantTypes("client_credentials")
27 | .scopes("all");
28 | //@formatter:on
29 | }
30 |
31 | @Override
32 | public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
33 | security.allowFormAuthenticationForClients()
34 | .checkTokenAccess("isAuthenticated()");
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/client-credentials/client-credentials-authorization-server/src/main/java/com/github/hellxz/oauth2/config/SecurityConfig.java:
--------------------------------------------------------------------------------
1 | package com.github.hellxz.oauth2.config;
2 |
3 | import org.springframework.context.annotation.Configuration;
4 | import org.springframework.security.config.annotation.web.builders.HttpSecurity;
5 | import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
6 | import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
7 |
8 | @Configuration
9 | @EnableWebSecurity
10 | public class SecurityConfig extends WebSecurityConfigurerAdapter {
11 |
12 | @Override
13 | protected void configure(HttpSecurity http) throws Exception {
14 | http.authorizeRequests().anyRequest().authenticated();
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/client-credentials/client-credentials-authorization-server/src/main/resources/application.properties:
--------------------------------------------------------------------------------
1 | server.port=8080
--------------------------------------------------------------------------------
/client-credentials/client-credentials-client/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 | client-credentials
7 | com.github.hellxz
8 | 0.0.1-SNAPSHOT
9 |
10 | 4.0.0
11 |
12 | client-credentials-client
13 |
14 |
15 |
16 | org.springframework.cloud
17 | spring-cloud-starter-openfeign
18 |
19 |
20 | commons-io
21 | commons-io
22 |
23 |
24 | org.apache.commons
25 | commons-lang3
26 |
27 |
28 |
--------------------------------------------------------------------------------
/client-credentials/client-credentials-client/src/main/java/com/github/hellxz/oauth2/ClientCredentialsClientApp.java:
--------------------------------------------------------------------------------
1 | package com.github.hellxz.oauth2;
2 |
3 | import org.springframework.boot.SpringApplication;
4 | import org.springframework.boot.autoconfigure.SpringBootApplication;
5 | import org.springframework.cloud.openfeign.EnableFeignClients;
6 |
7 | /**
8 | * 使用feign使用ok-http调用接口,测试拦截feign请求,获取token放置到请求头上
9 | */
10 | @SpringBootApplication
11 | @EnableFeignClients
12 | public class ClientCredentialsClientApp {
13 |
14 | public static void main(String[] args) {
15 | SpringApplication.run(ClientCredentialsClientApp.class, args);
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/client-credentials/client-credentials-client/src/main/java/com/github/hellxz/oauth2/config/SecureConfig.java:
--------------------------------------------------------------------------------
1 | package com.github.hellxz.oauth2.config;
2 |
3 | import org.springframework.context.annotation.Configuration;
4 | import org.springframework.security.config.annotation.web.builders.HttpSecurity;
5 | import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
6 | import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
7 |
8 | @Configuration
9 | @EnableWebSecurity
10 | public class SecureConfig extends WebSecurityConfigurerAdapter {
11 | @Override
12 | protected void configure(HttpSecurity http) throws Exception {
13 | //因为父工程依赖了spring security, 这里不做拦截
14 | http.authorizeRequests().antMatchers("/**").permitAll();
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/client-credentials/client-credentials-client/src/main/java/com/github/hellxz/oauth2/config/UaaProperties.java:
--------------------------------------------------------------------------------
1 | package com.github.hellxz.oauth2.config;
2 |
3 | import org.springframework.boot.context.properties.ConfigurationProperties;
4 | import org.springframework.stereotype.Component;
5 |
6 | @Component
7 | @ConfigurationProperties(prefix = "uaa")
8 | public class UaaProperties {
9 | private String clientId;
10 | private String clientSecret;
11 | private String tokenEndpoint;
12 |
13 | public String getClientId() {
14 | return clientId;
15 | }
16 |
17 | public void setClientId(String clientId) {
18 | this.clientId = clientId;
19 | }
20 |
21 | public String getClientSecret() {
22 | return clientSecret;
23 | }
24 |
25 | public void setClientSecret(String clientSecret) {
26 | this.clientSecret = clientSecret;
27 | }
28 |
29 | public String getTokenEndpoint() {
30 | return tokenEndpoint;
31 | }
32 |
33 | public void setTokenEndpoint(String tokenEndpoint) {
34 | this.tokenEndpoint = tokenEndpoint;
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/client-credentials/client-credentials-client/src/main/java/com/github/hellxz/oauth2/dto/UserDto.java:
--------------------------------------------------------------------------------
1 | package com.github.hellxz.oauth2.dto;
2 |
3 | import org.apache.commons.lang3.builder.ToStringBuilder;
4 |
5 | public class UserDto {
6 | private String username;
7 | private String email;
8 |
9 | public UserDto(String username, String email) {
10 | this.username = username;
11 | this.email = email;
12 | }
13 |
14 | public String getUsername() {
15 | return username;
16 | }
17 |
18 | public void setUsername(String username) {
19 | this.username = username;
20 | }
21 |
22 | public String getEmail() {
23 | return email;
24 | }
25 |
26 | public void setEmail(String email) {
27 | this.email = email;
28 | }
29 |
30 | @Override
31 | public String toString() {
32 | return ToStringBuilder.reflectionToString(this);
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/client-credentials/client-credentials-client/src/main/java/com/github/hellxz/oauth2/feign/UserFeignClient.java:
--------------------------------------------------------------------------------
1 | package com.github.hellxz.oauth2.feign;
2 |
3 | import com.github.hellxz.oauth2.dto.UserDto;
4 | import com.github.hellxz.oauth2.feign.fallback.UserFeignClientFallback;
5 | import org.springframework.cloud.openfeign.FeignClient;
6 | import org.springframework.web.bind.annotation.GetMapping;
7 | import org.springframework.web.bind.annotation.PathVariable;
8 |
9 | @FeignClient(name = "user-feign",url = "http://localhost:8081", fallback = UserFeignClientFallback.class)
10 | public interface UserFeignClient {
11 |
12 | @GetMapping("/user/{username}")
13 | UserDto getUser(@PathVariable("username") String username);
14 | }
15 |
--------------------------------------------------------------------------------
/client-credentials/client-credentials-client/src/main/java/com/github/hellxz/oauth2/feign/fallback/UserFeignClientFallback.java:
--------------------------------------------------------------------------------
1 | package com.github.hellxz.oauth2.feign.fallback;
2 |
3 | import com.github.hellxz.oauth2.dto.UserDto;
4 | import com.github.hellxz.oauth2.feign.UserFeignClient;
5 | import org.springframework.stereotype.Component;
6 |
7 | @Component
8 | public class UserFeignClientFallback implements UserFeignClient {
9 | @Override
10 | public UserDto getUser(String username) {
11 | System.err.println("调用接口失败");
12 | return null;
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/client-credentials/client-credentials-client/src/main/java/com/github/hellxz/oauth2/filter/FeignTokenInterceptor.java:
--------------------------------------------------------------------------------
1 | package com.github.hellxz.oauth2.filter;
2 |
3 | import com.github.hellxz.oauth2.config.UaaProperties;
4 | import com.github.hellxz.oauth2.utils.TokenUtils;
5 | import feign.RequestInterceptor;
6 | import feign.RequestTemplate;
7 | import org.apache.commons.lang3.StringUtils;
8 | import org.springframework.context.annotation.Configuration;
9 | import org.springframework.util.CollectionUtils;
10 |
11 | import javax.annotation.Resource;
12 | import java.util.*;
13 |
14 | /**
15 | * Feign拦截器,为请求头上加上token
16 | */
17 | @Configuration
18 | public class FeignTokenInterceptor implements RequestInterceptor {
19 |
20 | @Resource
21 | private UaaProperties uaaProperties;
22 |
23 | @Resource
24 | private TokenUtils tokenUtils;
25 |
26 | /**
27 | * 请求头中没有Authorization的,调用资源服务器获取token置于请求头,使请求可被访问
28 | * 使用客户端模式
29 | */
30 | @Override
31 | public void apply(RequestTemplate requestTemplate) {
32 | Map> headers = requestTemplate.headers();
33 | if (CollectionUtils.isEmpty(headers) || !headers.containsKey("Authorization")) {
34 | String clientId = uaaProperties.getClientId();
35 | String clientSecret = uaaProperties.getClientSecret();
36 | String tokenEndpoint = uaaProperties.getTokenEndpoint();
37 | String bearerToken = tokenUtils.getBearerTokenByClientCredentials(clientId, clientSecret, tokenEndpoint);
38 | if (StringUtils.isNotBlank(bearerToken)) {
39 | requestTemplate.header("Authorization", bearerToken);
40 | }
41 | }
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/client-credentials/client-credentials-client/src/main/java/com/github/hellxz/oauth2/utils/TokenUtils.java:
--------------------------------------------------------------------------------
1 | package com.github.hellxz.oauth2.utils;
2 |
3 | import com.fasterxml.jackson.annotation.JsonProperty;
4 | import org.apache.commons.lang3.builder.ToStringBuilder;
5 | import org.springframework.context.annotation.Bean;
6 | import org.springframework.http.HttpHeaders;
7 | import org.springframework.http.HttpMethod;
8 | import org.springframework.http.RequestEntity;
9 | import org.springframework.http.ResponseEntity;
10 | import org.springframework.stereotype.Component;
11 | import org.springframework.util.LinkedMultiValueMap;
12 | import org.springframework.util.MultiValueMap;
13 | import org.springframework.web.client.RestTemplate;
14 |
15 | import javax.annotation.Resource;
16 | import java.net.URI;
17 | import java.util.Objects;
18 |
19 | @Component
20 | public class TokenUtils {
21 |
22 | @Resource(name = "tokenTemplate")
23 | private RestTemplate tokenTemplate;
24 |
25 | public String getBearerTokenByClientCredentials(String clientId, String clientSecret, String tokenEndpoint){
26 | HttpHeaders httpHeaders = new HttpHeaders();
27 | httpHeaders.setBasicAuth(clientId, clientSecret);
28 | MultiValueMap params = new LinkedMultiValueMap<>();
29 | params.add("grant_type", "client_credentials");
30 | RequestEntity> requestEntity
31 | = new RequestEntity<>(params, httpHeaders, HttpMethod.POST, URI.create(tokenEndpoint));
32 | ResponseEntity exchange = tokenTemplate.exchange(requestEntity, TokenDTO.class);
33 | if (exchange.getStatusCode().is2xxSuccessful()) {
34 | return "Bearer " + Objects.requireNonNull(exchange.getBody()).getAccessToken();
35 | }else{
36 | return "";
37 | }
38 | }
39 |
40 | static class TokenDTO {
41 | @JsonProperty("access_token")
42 | private String accessToken;
43 | @JsonProperty("refresh_token")
44 | private String refreshToken;
45 | @JsonProperty("token_type")
46 | private String tokenType;
47 | @JsonProperty("expires_in")
48 | private String expiresIn;
49 | @JsonProperty("scope")
50 | private String scope;
51 |
52 | public String getRefreshToken() {
53 | return refreshToken;
54 | }
55 |
56 | public void setRefreshToken(String refreshToken) {
57 | this.refreshToken = refreshToken;
58 | }
59 |
60 | public String getAccessToken() {
61 | return accessToken;
62 | }
63 |
64 | public void setAccessToken(String accessToken) {
65 | this.accessToken = accessToken;
66 | }
67 |
68 | public String getTokenType() {
69 | return tokenType;
70 | }
71 |
72 | public void setTokenType(String tokenType) {
73 | this.tokenType = tokenType;
74 | }
75 |
76 | public String getExpiresIn() {
77 | return expiresIn;
78 | }
79 |
80 | public void setExpiresIn(String expiresIn) {
81 | this.expiresIn = expiresIn;
82 | }
83 |
84 | public String getScope() {
85 | return scope;
86 | }
87 |
88 | public void setScope(String scope) {
89 | this.scope = scope;
90 | }
91 |
92 | @Override
93 | public String toString() {
94 | return ToStringBuilder.reflectionToString(this);
95 | }
96 | }
97 |
98 | @Bean("tokenTemplate")
99 | public RestTemplate tokenTemplate(){
100 | return new RestTemplate();
101 | }
102 | }
103 |
--------------------------------------------------------------------------------
/client-credentials/client-credentials-client/src/main/java/com/github/hellxz/oauth2/web/UserController.java:
--------------------------------------------------------------------------------
1 | package com.github.hellxz.oauth2.web;
2 |
3 | import com.github.hellxz.oauth2.dto.UserDto;
4 | import com.github.hellxz.oauth2.feign.UserFeignClient;
5 | import org.springframework.web.bind.annotation.GetMapping;
6 | import org.springframework.web.bind.annotation.RestController;
7 |
8 | import javax.annotation.Resource;
9 |
10 | /**
11 | * 测试调用用户资源服务器的controller,用于测试
12 | */
13 | @RestController
14 | public class UserController {
15 |
16 | @Resource
17 | UserFeignClient userClient;
18 |
19 | @GetMapping("/user")
20 | public UserDto getResourceUser(){
21 | return userClient.getUser("test");
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/client-credentials/client-credentials-client/src/main/resources/application.yml:
--------------------------------------------------------------------------------
1 | server:
2 | port: 9001
3 | feign:
4 | okhttp:
5 | enabled: true
6 | uaa:
7 | clientId: user-center
8 | clientSecret: 12345
9 | tokenEndpoint: http://localhost:8080/oauth/token
10 |
--------------------------------------------------------------------------------
/client-credentials/client-credentials-resource-server/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 | client-credentials
7 | com.github.hellxz
8 | 0.0.1-SNAPSHOT
9 |
10 | 4.0.0
11 |
12 | client-credentials-resource-server
13 |
--------------------------------------------------------------------------------
/client-credentials/client-credentials-resource-server/src/main/java/com/github/hellxz/oauth2/ClientCredentialsResourceServerApp.java:
--------------------------------------------------------------------------------
1 | package com.github.hellxz.oauth2;
2 |
3 | import org.springframework.boot.SpringApplication;
4 | import org.springframework.boot.autoconfigure.SpringBootApplication;
5 |
6 | @SpringBootApplication
7 | public class ClientCredentialsResourceServerApp {
8 | public static void main(String[] args) {
9 | SpringApplication.run(ClientCredentialsResourceServerApp.class, args);
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/client-credentials/client-credentials-resource-server/src/main/java/com/github/hellxz/oauth2/config/ResourceServerConfig.java:
--------------------------------------------------------------------------------
1 | package com.github.hellxz.oauth2.config;
2 |
3 | import org.springframework.context.annotation.Bean;
4 | import org.springframework.context.annotation.Configuration;
5 | import org.springframework.security.config.annotation.web.builders.HttpSecurity;
6 | import org.springframework.security.config.http.SessionCreationPolicy;
7 | import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
8 | import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
9 | import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer;
10 | import org.springframework.security.oauth2.provider.token.RemoteTokenServices;
11 |
12 | @Configuration
13 | @EnableResourceServer
14 | public class ResourceServerConfig extends ResourceServerConfigurerAdapter {
15 |
16 | @Bean
17 | public RemoteTokenServices remoteTokenServices(){
18 | final RemoteTokenServices remoteTokenServices = new RemoteTokenServices();
19 | remoteTokenServices.setCheckTokenEndpointUrl("http://localhost:8080/oauth/check_token");
20 | remoteTokenServices.setClientId("user-center");
21 | remoteTokenServices.setClientSecret("12345");
22 | return remoteTokenServices;
23 | }
24 |
25 | @Override
26 | public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
27 | resources.stateless(true);
28 | }
29 |
30 | @Override
31 | public void configure(HttpSecurity http) throws Exception {
32 | http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED);
33 | http.authorizeRequests().anyRequest().authenticated();
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/client-credentials/client-credentials-resource-server/src/main/java/com/github/hellxz/oauth2/web/controller/ResourceController.java:
--------------------------------------------------------------------------------
1 | package com.github.hellxz.oauth2.web.controller;
2 |
3 | import com.github.hellxz.oauth2.web.vo.UserVO;
4 | import org.springframework.web.bind.annotation.GetMapping;
5 | import org.springframework.web.bind.annotation.PathVariable;
6 | import org.springframework.web.bind.annotation.RestController;
7 |
8 | @RestController
9 | public class ResourceController {
10 |
11 | @GetMapping("/user/{username}")
12 | public UserVO user(@PathVariable String username){
13 | return new UserVO(username, username + "@foxmail.com");
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/client-credentials/client-credentials-resource-server/src/main/java/com/github/hellxz/oauth2/web/vo/UserVO.java:
--------------------------------------------------------------------------------
1 | package com.github.hellxz.oauth2.web.vo;
2 |
3 | public class UserVO {
4 | private String username;
5 | private String email;
6 |
7 | public UserVO(String username, String email) {
8 | this.username = username;
9 | this.email = email;
10 | }
11 |
12 | public String getUsername() {
13 | return username;
14 | }
15 |
16 | public void setUsername(String username) {
17 | this.username = username;
18 | }
19 |
20 | public String getEmail() {
21 | return email;
22 | }
23 |
24 | public void setEmail(String email) {
25 | this.email = email;
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/client-credentials/client-credentials-resource-server/src/main/resources/application.properties:
--------------------------------------------------------------------------------
1 | server.port=8081
--------------------------------------------------------------------------------
/client-credentials/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 | spring-security-oauth2-learn
7 | com.github.hellxz
8 | 0.0.1-SNAPSHOT
9 |
10 | 4.0.0
11 |
12 | client-credentials
13 | pom
14 |
15 | client-credentials-authorization-server
16 | client-credentials-resource-server
17 | client-credentials-client
18 |
19 |
20 |
21 |
22 | org.springframework.security.oauth
23 | spring-security-oauth2
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/implicit/README.md:
--------------------------------------------------------------------------------
1 | ## 简化模式(隐式授权模式)Demo
2 | 1. 客户端拼url重定向,用户登录并授权
3 | GET请求
4 | ```
5 | http://localhost:8080/oauth/authorize?client_id=client-a&redirect_uri=http://localhost:9001/callback&response_type=token&scope=read_user_info
6 | ```
7 | 请求参数列表:
8 | - client_id=客户端id
9 | - redirect_uri=回调url 一定要与授权服务器配置保持一致,否则得不到授权码
10 | - response_type=token 简化模式必须是token
11 | - scope=作用域 与授权服务器配置保持一致
12 | - state=自定义串(可选)
13 |
14 |
15 | > `state`这个字段可选填,在生产环境下可以传加密串用来验证授权回调请求可信
16 | > 注意: 简化模式(隐式授权模式)不需要client_secret >
17 | >
18 |
19 | 2. 授权服务器返回token
20 | ```
21 | http://localhost:9001/callback#access_token=d87e1391-78a3-476f-afda-752e5884a93a&token_type=bearer&expires_in=119
22 | ```
23 | 3. 客户端保存token,并在请求时带上此token
24 | ```
25 | curl -X GET \
26 | http://localhost:8081/user/hellxz001 \
27 | -H 'Authorization: Bearer 0b68fd19-15a5-488e-bc80-dd918cd23cf8' \
28 | ```
29 | 响应结果
30 | ```json
31 | {
32 | "username": "hellxz001",
33 | "email": "hellxz001@foxmail.com"
34 | }
35 | ```
36 |
37 | ## 简化模式流程梳理
38 | 1. 用户请求访问资源服务器资源,客户端(浏览器端)发现本地没有缓存用户授权token
39 | 2. 客户端拼url重定向到授权服务器请求页面
40 | 3. 用户登录,授权
41 | 4. 授权成功后,回调url返回token给客户端
42 | 5. 客户端收到token后,保存token并在请求时带上token,访问资源
43 |
--------------------------------------------------------------------------------
/implicit/implicit-authorization-server/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 | implicit
7 | com.github.hellxz
8 | 0.0.1-SNAPSHOT
9 |
10 | 4.0.0
11 |
12 | implicit-authorization-server
13 |
--------------------------------------------------------------------------------
/implicit/implicit-authorization-server/src/main/java/com/github/hellxz/oauth2/ImplicitAuthorizationServerApplication.java:
--------------------------------------------------------------------------------
1 | package com.github.hellxz.oauth2;
2 |
3 | import org.springframework.boot.SpringApplication;
4 | import org.springframework.boot.autoconfigure.SpringBootApplication;
5 |
6 | @SpringBootApplication
7 | public class ImplicitAuthorizationServerApplication {
8 | public static void main(String[] args) {
9 | SpringApplication.run(ImplicitAuthorizationServerApplication.class, args);
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/implicit/implicit-authorization-server/src/main/java/com/github/hellxz/oauth2/config/AuthorizationConfig.java:
--------------------------------------------------------------------------------
1 | package com.github.hellxz.oauth2.config;
2 |
3 | import org.springframework.beans.factory.annotation.Autowired;
4 | import org.springframework.context.annotation.Configuration;
5 | import org.springframework.security.crypto.password.PasswordEncoder;
6 | import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
7 | import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
8 | import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
9 | import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
10 |
11 | //授权服务器配置
12 | @Configuration
13 | @EnableAuthorizationServer //开启授权服务
14 | public class AuthorizationConfig extends AuthorizationServerConfigurerAdapter {
15 |
16 | @Autowired
17 | private PasswordEncoder passwordEncoder;
18 |
19 | @Override
20 | public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
21 | //允许表单提交
22 | security.allowFormAuthenticationForClients()
23 | .checkTokenAccess("permitAll()"); //参数与security访问控制一致
24 | }
25 |
26 | @Override
27 | public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
28 | // @formatter: off
29 | clients.inMemory()
30 | .withClient("client-a") //client端唯一标识
31 | .authorizedGrantTypes("implicit") //授权模式标识
32 | .accessTokenValiditySeconds(120) //访问令牌的有效期,这里设置120s
33 | .scopes("read_user_info") //作用域
34 | .resourceIds("resource1") //资源id
35 | .redirectUris("http://localhost:9001/callback") //回调地址
36 | .and()
37 | .withClient("resource-server") //资源服务器校验token时用的客户端信息,仅需要client_id与密码
38 | .secret(passwordEncoder.encode("test"));
39 | // @formatter: on
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/implicit/implicit-authorization-server/src/main/java/com/github/hellxz/oauth2/config/SecurityConfig.java:
--------------------------------------------------------------------------------
1 | package com.github.hellxz.oauth2.config;
2 |
3 | import org.springframework.context.annotation.Bean;
4 | import org.springframework.context.annotation.Configuration;
5 | import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
6 | import org.springframework.security.config.annotation.web.builders.HttpSecurity;
7 | import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
8 | import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
9 | import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
10 | import org.springframework.security.crypto.password.PasswordEncoder;
11 |
12 | import java.util.Collections;
13 |
14 | @Configuration
15 | @EnableWebSecurity
16 | public class SecurityConfig extends WebSecurityConfigurerAdapter {
17 |
18 | @Bean
19 | public PasswordEncoder passwordEncoder(){
20 | return new BCryptPasswordEncoder();
21 | }
22 |
23 | @Override
24 | protected void configure(AuthenticationManagerBuilder auth) throws Exception {
25 | // @formatter: off
26 | auth.inMemoryAuthentication()
27 | .withUser("hellxz")
28 | .password(passwordEncoder().encode("xyz"))
29 | .authorities(Collections.emptyList());
30 | // @formatter: on
31 | }
32 |
33 | @Override
34 | protected void configure(HttpSecurity http) throws Exception {
35 | http.authorizeRequests()
36 | .anyRequest().authenticated() //所有请求都需要通过认证
37 | .and()
38 | .httpBasic() //Basic提交
39 | .and()
40 | .csrf().disable(); //关跨域保护
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/implicit/implicit-authorization-server/src/main/resources/application.properties:
--------------------------------------------------------------------------------
1 | server.port=8080
--------------------------------------------------------------------------------
/implicit/implicit-resource-server/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 | implicit
7 | com.github.hellxz
8 | 0.0.1-SNAPSHOT
9 |
10 | 4.0.0
11 |
12 | implicit-resource-server
13 |
--------------------------------------------------------------------------------
/implicit/implicit-resource-server/src/main/java/com/github/hellxz/oauth2/ImplicitResourceServerApp.java:
--------------------------------------------------------------------------------
1 | package com.github.hellxz.oauth2;
2 |
3 | import org.springframework.boot.SpringApplication;
4 | import org.springframework.boot.autoconfigure.SpringBootApplication;
5 |
6 | /**
7 | * 授权服务器 入口
8 | *
9 | * @author hellxz
10 | */
11 | @SpringBootApplication
12 | public class ImplicitResourceServerApp {
13 |
14 | public static void main(String[] args) {
15 | SpringApplication.run(ImplicitResourceServerApp.class, args);
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/implicit/implicit-resource-server/src/main/java/com/github/hellxz/oauth2/config/ResourceConfig.java:
--------------------------------------------------------------------------------
1 | package com.github.hellxz.oauth2.config;
2 |
3 | import org.springframework.context.annotation.Bean;
4 | import org.springframework.context.annotation.Configuration;
5 | import org.springframework.context.annotation.Primary;
6 | import org.springframework.security.config.annotation.web.builders.HttpSecurity;
7 | import org.springframework.security.config.http.SessionCreationPolicy;
8 | import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
9 | import org.springframework.security.crypto.password.PasswordEncoder;
10 | import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
11 | import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
12 | import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer;
13 | import org.springframework.security.oauth2.provider.token.RemoteTokenServices;
14 |
15 | @Configuration
16 | @EnableResourceServer
17 | public class ResourceConfig extends ResourceServerConfigurerAdapter {
18 |
19 | @Bean
20 | public PasswordEncoder passwordEncoder() {
21 | return new BCryptPasswordEncoder();
22 | }
23 |
24 | @Primary
25 | @Bean
26 | public RemoteTokenServices remoteTokenServices() {
27 | final RemoteTokenServices tokenServices = new RemoteTokenServices();
28 | tokenServices.setCheckTokenEndpointUrl("http://localhost:8080/oauth/check_token");
29 | //这里的clientId和secret对应资源服务器信息,授权服务器处需要配置
30 | tokenServices.setClientId("resource-server");
31 | tokenServices.setClientSecret("test");
32 | return tokenServices;
33 | }
34 |
35 | @Override
36 | public void configure(HttpSecurity http) throws Exception {
37 | //设置创建session策略
38 | http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED);
39 | //@formatter:off
40 | //所有请求必须授权
41 | http.authorizeRequests()
42 | .anyRequest().authenticated();
43 | //@formatter:on
44 | }
45 |
46 | @Override
47 | public void configure(ResourceServerSecurityConfigurer resources) {
48 | resources.resourceId("resource1").stateless(true);
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/implicit/implicit-resource-server/src/main/java/com/github/hellxz/oauth2/web/controller/ResourceController.java:
--------------------------------------------------------------------------------
1 | package com.github.hellxz.oauth2.web.controller;
2 |
3 | import com.github.hellxz.oauth2.web.vo.UserVO;
4 | import org.springframework.security.core.context.SecurityContextHolder;
5 | import org.springframework.web.bind.annotation.GetMapping;
6 | import org.springframework.web.bind.annotation.PathVariable;
7 | import org.springframework.web.bind.annotation.RestController;
8 |
9 | @RestController
10 | public class ResourceController {
11 |
12 | @GetMapping("/user/{username}")
13 | public UserVO user(@PathVariable String username){
14 | System.err.println(SecurityContextHolder.getContext().getAuthentication());
15 | return new UserVO(username, username + "@foxmail.com");
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/implicit/implicit-resource-server/src/main/java/com/github/hellxz/oauth2/web/vo/UserVO.java:
--------------------------------------------------------------------------------
1 | package com.github.hellxz.oauth2.web.vo;
2 |
3 | public class UserVO {
4 | private String username;
5 | private String email;
6 |
7 | public UserVO(String username, String email) {
8 | this.username = username;
9 | this.email = email;
10 | }
11 |
12 | public String getUsername() {
13 | return username;
14 | }
15 |
16 | public void setUsername(String username) {
17 | this.username = username;
18 | }
19 |
20 | public String getEmail() {
21 | return email;
22 | }
23 |
24 | public void setEmail(String email) {
25 | this.email = email;
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/implicit/implicit-resource-server/src/main/resources/application.properties:
--------------------------------------------------------------------------------
1 | server.port=8081
--------------------------------------------------------------------------------
/implicit/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 | spring-security-oauth2-learn
7 | com.github.hellxz
8 | 0.0.1-SNAPSHOT
9 |
10 | 4.0.0
11 |
12 | implicit
13 | pom
14 |
15 | implicit-authorization-server
16 | implicit-resource-server
17 |
18 |
19 |
20 |
21 | org.springframework.security.oauth
22 | spring-security-oauth2
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/jwt/README.md:
--------------------------------------------------------------------------------
1 | # JWT
2 | 这部分demo并非是OAuth2授权模式之一,是使用JWT作为token的演示代码
3 |
4 | ## JWT概念
5 | JWT是一种自包含的加密token,整体分为三部分:
6 | - Header : 标头通常由两部分组成:令牌的类型(即JWT)和所使用的签名算法,例如HMAC SHA256或RSA。标头通常由两部分组成:令牌的类型(即JWT)和所使用的签名算法,例如HMAC SHA256或RSA。
7 | - Payload : 令牌的第二部分是有效负载,其中包含声明。声明是有关实体(通常是用户)和其他数据的声明。共有三种类型的claims:registered, public, and private claims.。
8 | - Signature : 要创建签名部分,您必须获取编码的Header,编码的有效Payload,密钥,标头中指定的算法,并对其进行签名。
9 | ### JWT结构
10 | > 每个json块使用Base64加密,然后使用`.`连接在一起
11 |
12 | 其结构为`Header.Payload.Signature`
13 |
14 | e.g.
15 |
16 | 
17 |
18 | ### Header
19 | Header这部分包含令牌所用的算法(alg:algorithm, 常用的有HMAC SHA256或RSA)和 令牌的类型(typ: Token Type,即JWT)
20 | 未被加密前的样子就像
21 | ```json
22 | {
23 | "alg": "HS256",
24 | "typ": "JWT"
25 | }
26 | ```
27 | Header部分使用Base64Url进行加密
28 | ### Payload
29 | Payload这部分包含token的信息,这部分可以包含 已被注册信息、公有的信息、私有的信息,提供了很多可以自定义的部分
30 | 官方给了一些推荐使用的已定义的参数名(已被注册信息):
31 | - "iss" (Issuer) Claim
32 | - "sub" (Subject) Claim
33 | - "aud" (Audience) Claim
34 | - "exp" (Expiration Time) Claim
35 | - "nbf" (Not Before) Claim
36 | - "iat" (Issued At) Claim
37 | - "jti" (JWT ID) Claim
38 | 公有的信息、私有的信息都是自定义的,注意不要与官方给的冲突即可,另外注意保持参数尽量少且不要暴露隐私数据
39 |
40 | Payload部分使用Base64Url进行加密
41 | ### Signature
42 | 签名部分使用Header中定义的算法与密钥,把经过Base64Url加密的`Header.Payload`进行加密,得出签名。用来验证此token是授权服务器颁发的,而不是伪造的
43 |
44 | demo中使用的是对称密钥加密
45 |
46 | ## 使用方式
47 | 与普通的token使用一样,在请求头中添加`Authorization:Bearer 你的token`
48 |
49 | ## 使用JWT的好处
50 | 不使用session保持会话,实现无状态服务,避免大量session对服务器的资源使用,从而容易扩展,对于分布式和微服务应用特别多
51 |
52 | 另外,一般来说,JWT是自包含的token,使用它授权服务器就只需要颁发一次token,资源服务器可以通过这个token直接解析出用户信息,同时也可以减少授权服务器的请求次数
53 |
54 | ## 使用JWT的缺点
55 | 缺点就是JWT的token没有立即revoke(收回)权限的功能,只能等待token过期
56 |
57 | 所以,使用JWT时,请尽量设置较短的过期时间,保证服务安全
--------------------------------------------------------------------------------
/jwt/jwt-authorization-server/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 | jwt
7 | com.github.hellxz
8 | 0.0.1-SNAPSHOT
9 |
10 | 4.0.0
11 |
12 | jwt-authorization-server
13 |
--------------------------------------------------------------------------------
/jwt/jwt-authorization-server/src/main/java/com/github/hellxz/oauth2/JwtAuthorizationServerApp.java:
--------------------------------------------------------------------------------
1 | package com.github.hellxz.oauth2;
2 |
3 | import org.springframework.boot.SpringApplication;
4 | import org.springframework.boot.autoconfigure.SpringBootApplication;
5 |
6 | /**
7 | * 授权服务器 入口
8 | *
9 | * @author hellxz
10 | */
11 | @SpringBootApplication
12 | public class JwtAuthorizationServerApp {
13 |
14 | public static void main(String[] args) {
15 | SpringApplication.run(JwtAuthorizationServerApp.class, args);
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/jwt/jwt-authorization-server/src/main/java/com/github/hellxz/oauth2/config/AuthorizationConfig.java:
--------------------------------------------------------------------------------
1 | package com.github.hellxz.oauth2.config;
2 |
3 | import org.springframework.beans.factory.annotation.Autowired;
4 | import org.springframework.context.annotation.Bean;
5 | import org.springframework.context.annotation.Configuration;
6 | import org.springframework.core.io.ClassPathResource;
7 | import org.springframework.security.authentication.AuthenticationManager;
8 | import org.springframework.security.core.userdetails.UserDetailsService;
9 | import org.springframework.security.crypto.password.PasswordEncoder;
10 | import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
11 | import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
12 | import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
13 | import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
14 | import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
15 | import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
16 | import org.springframework.security.oauth2.provider.token.store.JwtTokenStore;
17 | import org.springframework.security.oauth2.provider.token.store.KeyStoreKeyFactory;
18 |
19 | //授权服务器配置
20 | @Configuration
21 | @EnableAuthorizationServer //开启授权服务
22 | public class AuthorizationConfig extends AuthorizationServerConfigurerAdapter {
23 |
24 | @Autowired
25 | private AuthenticationManager authenticationManager;
26 |
27 | @Autowired
28 | public UserDetailsService userDetailsService;
29 |
30 | @Autowired
31 | private PasswordEncoder passwordEncoder;
32 |
33 | @Override
34 | public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
35 | //允许表单提交
36 | security.allowFormAuthenticationForClients()
37 | .checkTokenAccess("permitAll()") //这里这两个配置只是用来测试使用,生产环境可以关闭,jwt不需要再去授权服务器校验token
38 | .tokenKeyAccess("permitAll()");
39 | }
40 |
41 | @Override
42 | public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
43 | // @formatter: off
44 | clients.inMemory()
45 | .withClient("client-a") //client端唯一标识
46 | .secret(passwordEncoder.encode("client-a-secret")) //client-a的密码,这里的密码应该是加密后的
47 | .authorizedGrantTypes("client_credentials","password", "refresh_token") //授权模式标识,开启刷新token功能
48 | .scopes("read_user_info", "service", "users") //作用域
49 | .resourceIds("resource1") //资源id,如不需限制资源id,注释此处即可
50 | .redirectUris("http://localhost:9001/callback"); //回调地址
51 |
52 | // @formatter: on
53 | }
54 |
55 | @Override
56 | public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
57 | endpoints.authenticationManager(authenticationManager)
58 | .userDetailsService(userDetailsService)
59 | .tokenStore(jwtTokenStore())
60 | .accessTokenConverter(jwtAccessTokenConverter());
61 | }
62 |
63 | /**
64 | * jwt访问token转换器
65 | */
66 | @Bean
67 | public JwtAccessTokenConverter jwtAccessTokenConverter(){
68 | JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
69 | // converter.setSigningKey("my-sign-key"); //密钥,默认是HMACSHA256对称加密
70 | KeyStoreKeyFactory storeKeyFactory = new KeyStoreKeyFactory(
71 | new ClassPathResource("hellxz-jwt.jks"), "hellxzTest".toCharArray());
72 | converter.setKeyPair(storeKeyFactory.getKeyPair("hellxz-jwt"));
73 | return converter;
74 | }
75 |
76 | /**
77 | * jwt的token存储对象
78 | */
79 | @Bean
80 | public JwtTokenStore jwtTokenStore(){
81 | return new JwtTokenStore(jwtAccessTokenConverter());
82 | }
83 | }
84 |
--------------------------------------------------------------------------------
/jwt/jwt-authorization-server/src/main/java/com/github/hellxz/oauth2/config/SecurityConfig.java:
--------------------------------------------------------------------------------
1 | package com.github.hellxz.oauth2.config;
2 |
3 | import org.springframework.context.annotation.Bean;
4 | import org.springframework.context.annotation.Configuration;
5 | import org.springframework.security.authentication.AuthenticationManager;
6 | import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
7 | import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
8 | import org.springframework.security.config.annotation.web.builders.HttpSecurity;
9 | import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
10 | import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
11 | import org.springframework.security.core.userdetails.User;
12 | import org.springframework.security.core.userdetails.UserDetails;
13 | import org.springframework.security.core.userdetails.UserDetailsService;
14 | import org.springframework.security.core.userdetails.UsernameNotFoundException;
15 | import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
16 | import org.springframework.security.crypto.password.PasswordEncoder;
17 | import org.springframework.util.StringUtils;
18 |
19 | import java.util.Collections;
20 |
21 | /**
22 | * 这里记个坑:
23 | * 1. 重写了configure(AuthenticationManagerBuilder auth)方法提供登录用户信息时,无需再在AuthenticationManager和UserDetailsService中再写一遍查用户信息的操作
24 | * 2. 声明bean为UserDetailsService不要使用super.userDetailsServiceBean(),当刷新token时会造成StackOverFlow,转而使用super.userDetailsService()便好
25 | */
26 | @Configuration
27 | @EnableWebSecurity
28 | public class SecurityConfig extends WebSecurityConfigurerAdapter {
29 |
30 | @Bean
31 | public AuthenticationManager authenticationManager() throws Exception {
32 | return super.authenticationManager();
33 | }
34 |
35 | @Bean
36 | public UserDetailsService userDetailsService(){
37 | return super.userDetailsService();
38 | }
39 |
40 | @Bean
41 | public PasswordEncoder passwordEncoder(){
42 | return new BCryptPasswordEncoder();
43 | }
44 |
45 | @Override
46 | protected void configure(AuthenticationManagerBuilder auth) throws Exception {
47 | // @formatter: off
48 | auth.inMemoryAuthentication()
49 | .withUser("hellxz")
50 | .password(passwordEncoder().encode("xyz"))
51 | .authorities(Collections.emptyList());
52 | // @formatter: on
53 | }
54 |
55 | @Override
56 | protected void configure(HttpSecurity http) throws Exception {
57 | http.authorizeRequests()
58 | .anyRequest().authenticated() //所有请求都需要通过认证
59 | .and()
60 | .httpBasic() //Basic提交
61 | .and()
62 | .csrf().disable(); //关跨域保护
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/jwt/jwt-authorization-server/src/main/resources/application.properties:
--------------------------------------------------------------------------------
1 | server.port=8080
--------------------------------------------------------------------------------
/jwt/jwt-authorization-server/src/main/resources/hellxz-jwt.jks:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hellxz/spring-security-oauth2-learn/f8c9843f70108fab99e888da8acd780ccace1818/jwt/jwt-authorization-server/src/main/resources/hellxz-jwt.jks
--------------------------------------------------------------------------------
/jwt/jwt-resource-server/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 | jwt
7 | com.github.hellxz
8 | 0.0.1-SNAPSHOT
9 |
10 | 4.0.0
11 |
12 | jwt-resource-server
13 |
14 |
--------------------------------------------------------------------------------
/jwt/jwt-resource-server/src/main/java/com/github/hellxz/oauth2/JwtResourceServerApp.java:
--------------------------------------------------------------------------------
1 | package com.github.hellxz.oauth2;
2 |
3 | import org.springframework.boot.SpringApplication;
4 | import org.springframework.boot.autoconfigure.SpringBootApplication;
5 |
6 | /**
7 | * 授权服务器 入口
8 | *
9 | * @author hellxz
10 | */
11 | @SpringBootApplication
12 | public class JwtResourceServerApp {
13 |
14 | public static void main(String[] args) {
15 | SpringApplication.run(JwtResourceServerApp.class, args);
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/jwt/jwt-resource-server/src/main/java/com/github/hellxz/oauth2/config/ResourceConfig.java:
--------------------------------------------------------------------------------
1 | package com.github.hellxz.oauth2.config;
2 |
3 | import org.springframework.context.annotation.Bean;
4 | import org.springframework.context.annotation.Configuration;
5 | import org.springframework.context.annotation.Primary;
6 | import org.springframework.core.io.ClassPathResource;
7 | import org.springframework.core.io.Resource;
8 | import org.springframework.security.config.annotation.web.builders.HttpSecurity;
9 | import org.springframework.security.config.http.SessionCreationPolicy;
10 | import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
11 | import org.springframework.security.crypto.password.PasswordEncoder;
12 | import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
13 | import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
14 | import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer;
15 | import org.springframework.security.oauth2.provider.token.RemoteTokenServices;
16 | import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
17 | import org.springframework.security.oauth2.provider.token.store.JwtTokenStore;
18 | import org.springframework.util.FileCopyUtils;
19 |
20 | import java.io.IOException;
21 |
22 | @Configuration
23 | @EnableResourceServer
24 | public class ResourceConfig extends ResourceServerConfigurerAdapter {
25 |
26 | @Bean
27 | public PasswordEncoder passwordEncoder() {
28 | return new BCryptPasswordEncoder();
29 | }
30 |
31 | // /**
32 | // * 这里使用的是调用授权服务器接口进行校验token的,除了这种方式,如果授权服务器将token保存在某些存储器中,可以使用访问存储器来实现
33 | // */
34 | // @Primary
35 | // @Bean
36 | // public RemoteTokenServices remoteTokenServices() {
37 | // final RemoteTokenServices tokenServices = new RemoteTokenServices();
38 | // tokenServices.setCheckTokenEndpointUrl("http://localhost:8080/oauth/check_token");
39 | // tokenServices.setClientId("client-a");
40 | // tokenServices.setClientSecret("client-a-secret");
41 | // return tokenServices;
42 | // }
43 |
44 | @Override
45 | public void configure(HttpSecurity http) throws Exception {
46 | //设置创建session策略
47 | http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED);
48 | //@formatter:off
49 | //所有请求必须授权
50 | http.authorizeRequests()
51 | .anyRequest().authenticated();
52 | //@formatter:on
53 | }
54 |
55 | @Override
56 | public void configure(ResourceServerSecurityConfigurer resources) {
57 | //@formatter:off
58 | //如不需要限制资源id,请在授权配置处去除resourceIds的配置
59 | resources.resourceId("resource1")
60 | .tokenStore(jwtTokenStore());
61 | //@formatter:on
62 | }
63 |
64 | /**
65 | * jwt访问token转换器
66 | */
67 | @Bean
68 | public JwtAccessTokenConverter jwtAccessTokenConverter(){
69 | JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
70 | // converter.setSigningKey("my-sign-key"); //对称加密算法使用与授权服务器相同的signingKey
71 | Resource resource = new ClassPathResource("public.cert");
72 | String publicKey;
73 | try {
74 | publicKey = new String(FileCopyUtils.copyToByteArray(resource.getInputStream()));
75 | } catch (IOException e) {
76 | throw new RuntimeException(e);
77 | }
78 | converter.setVerifierKey(publicKey);
79 | return converter;
80 | }
81 |
82 | /**
83 | * jwt的token存储对象
84 | */
85 | @Bean
86 | public JwtTokenStore jwtTokenStore(){
87 | return new JwtTokenStore(jwtAccessTokenConverter());
88 | }
89 |
90 | }
91 |
--------------------------------------------------------------------------------
/jwt/jwt-resource-server/src/main/java/com/github/hellxz/oauth2/web/controller/ResourceController.java:
--------------------------------------------------------------------------------
1 | package com.github.hellxz.oauth2.web.controller;
2 |
3 | import com.github.hellxz.oauth2.web.vo.UserVO;
4 | import org.slf4j.Logger;
5 | import org.slf4j.LoggerFactory;
6 | import org.springframework.security.core.context.SecurityContext;
7 | import org.springframework.security.core.context.SecurityContextHolder;
8 | import org.springframework.web.bind.annotation.GetMapping;
9 | import org.springframework.web.bind.annotation.PathVariable;
10 | import org.springframework.web.bind.annotation.RestController;
11 |
12 | @RestController
13 | public class ResourceController {
14 | private static final Logger log = LoggerFactory.getLogger(ResourceController.class);
15 |
16 | @GetMapping("/user/{username}")
17 | public UserVO user(@PathVariable String username){
18 | log.info("{}", SecurityContextHolder.getContext().getAuthentication());
19 | return new UserVO(username, username + "@foxmail.com");
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/jwt/jwt-resource-server/src/main/java/com/github/hellxz/oauth2/web/vo/UserVO.java:
--------------------------------------------------------------------------------
1 | package com.github.hellxz.oauth2.web.vo;
2 |
3 | public class UserVO {
4 | private String username;
5 | private String email;
6 |
7 | public UserVO(String username, String email) {
8 | this.username = username;
9 | this.email = email;
10 | }
11 |
12 | public String getUsername() {
13 | return username;
14 | }
15 |
16 | public void setUsername(String username) {
17 | this.username = username;
18 | }
19 |
20 | public String getEmail() {
21 | return email;
22 | }
23 |
24 | public void setEmail(String email) {
25 | this.email = email;
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/jwt/jwt-resource-server/src/main/resources/application.properties:
--------------------------------------------------------------------------------
1 | server.port=8081
--------------------------------------------------------------------------------
/jwt/jwt-resource-server/src/main/resources/public.cert:
--------------------------------------------------------------------------------
1 | -----BEGIN PUBLIC KEY-----
2 | MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxU7zulFUVBXmZD28xwM4
3 | ul5e9yFrToLgWKHlNLlp904/GbiWBoZ4tcBcNq3VxLGBN9VOqfP1P5C7fRgz95UI
4 | 7ShKCKgsFFGL2rAqsplMDClN/adfsxmpF06rVIkGgce9tR0Q0iONcaN+b/lArK4T
5 | Au76QsQwn9MLXlznVfczclZOZSfDNju+1JuBzqt6fEPWqalBUVYdV0zCUDG8ikN1
6 | l9D0m1tSSaKpiTrU2yEUGUji+79Ury7Y8BClEX6d4CTl9TQAhL5g32GoJEc0S2y+
7 | 0bqeqUsv1nUt9KiJT9kiOvA+Q7o2T8OHuqQT9le7kvmIi4gSX5vSNvvZagE2Uglh
8 | zQIDAQAB
9 | -----END PUBLIC KEY-----
--------------------------------------------------------------------------------
/jwt/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 | spring-security-oauth2-learn
7 | com.github.hellxz
8 | 0.0.1-SNAPSHOT
9 |
10 | 4.0.0
11 |
12 | jwt
13 | pom
14 |
15 |
16 | jwt-authorization-server
17 | jwt-resource-server
18 |
19 |
20 |
21 |
22 | org.springframework.security.oauth
23 | spring-security-oauth2
24 |
25 |
26 | org.springframework.security
27 | spring-security-jwt
28 |
29 |
30 |
--------------------------------------------------------------------------------
/password/README.md:
--------------------------------------------------------------------------------
1 | ## 密码模式Demo
2 | 密码模式用户与其它几个模式相比,更加简单一些,用户访问资源时,客户端(浏览器)跳转自己的登录页面,
3 | 用户输入账号密码提交表单,表单提交时带上客户端的账号和密码+用户账户密码+scope+grant_type
4 | 授权服务器校验通过后直接返回token
5 | > 这里要注意:表单提交的uri是`/oauth/token`
6 |
7 | 1. 带上客户端账号密码与用户账户密码获取token
8 | ```
9 | curl -X POST --user client-a:client-a-secret http://localhost:8080/oauth/token -H "accept: application/json" -H "content-type: application/x-www-form-urlencoded" -d "grant_type=password&username=hellxz&password=xyz&scope=read_scope"
10 | ```
11 | 返回token
12 | ```json
13 | {
14 | "access_token": "58d25f8c-ea0e-40e0-9b55-9d7ef25c8145",
15 | "token_type": "bearer",
16 | "expires_in": 43199,
17 | "scope": "read_scope"
18 | }
19 | ```
20 | 2. 使用token访问资源
21 | ```
22 | curl -X GET \
23 | http://localhost:8081/user/hellxz001 \
24 | -H 'Authorization: Bearer 58d25f8c-ea0e-40e0-9b55-9d7ef25c8145' \
25 | ```
26 | 返回响应
27 | ```json
28 | {
29 | "username": "hellxz001",
30 | "email": "hellxz001@foxmail.com"
31 | }
32 | ```
33 |
34 |
--------------------------------------------------------------------------------
/password/password-authorization-server/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 | password
7 | com.github.hellxz
8 | 0.0.1-SNAPSHOT
9 |
10 | 4.0.0
11 |
12 | password-authorization-server
13 |
14 |
15 |
--------------------------------------------------------------------------------
/password/password-authorization-server/src/main/java/com/github/hellxz/oauth2/PasswordAuthorizationApp.java:
--------------------------------------------------------------------------------
1 | package com.github.hellxz.oauth2;
2 |
3 | import org.springframework.boot.SpringApplication;
4 | import org.springframework.boot.autoconfigure.SpringBootApplication;
5 |
6 | @SpringBootApplication
7 | public class PasswordAuthorizationApp {
8 | public static void main(String[] args) {
9 | SpringApplication.run(PasswordAuthorizationApp.class, args);
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/password/password-authorization-server/src/main/java/com/github/hellxz/oauth2/config/AuthorizationConfig.java:
--------------------------------------------------------------------------------
1 | package com.github.hellxz.oauth2.config;
2 |
3 | import org.springframework.beans.factory.annotation.Autowired;
4 | import org.springframework.context.annotation.Configuration;
5 | import org.springframework.security.authentication.AuthenticationManager;
6 | import org.springframework.security.crypto.password.PasswordEncoder;
7 | import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
8 | import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
9 | import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
10 | import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
11 | import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
12 |
13 | @Configuration
14 | @EnableAuthorizationServer
15 | public class AuthorizationConfig extends AuthorizationServerConfigurerAdapter {
16 |
17 | @Autowired
18 | private AuthenticationManager authenticationManager;
19 |
20 | @Autowired
21 | public PasswordEncoder passwordEncoder;
22 |
23 | //配置客户端
24 | @Override
25 | public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
26 | //@formatter:off
27 | clients.inMemory()
28 | .withClient("client-a")
29 | .secret(passwordEncoder.encode("client-a-secret"))
30 | .authorizedGrantTypes("password")
31 | .scopes("read_scope");
32 | //@formatter:on
33 | }
34 |
35 | @Override
36 | public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
37 | endpoints.authenticationManager(authenticationManager);
38 | }
39 |
40 | @Override
41 | public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
42 | security.allowFormAuthenticationForClients()
43 | .checkTokenAccess("isAuthenticated()");
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/password/password-authorization-server/src/main/java/com/github/hellxz/oauth2/config/SecurityConfig.java:
--------------------------------------------------------------------------------
1 | package com.github.hellxz.oauth2.config;
2 |
3 | import org.springframework.context.annotation.Bean;
4 | import org.springframework.context.annotation.Configuration;
5 | import org.springframework.security.authentication.AuthenticationManager;
6 | import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
7 | import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
8 | import org.springframework.security.config.annotation.web.builders.HttpSecurity;
9 | import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
10 | import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
11 | import org.springframework.security.core.userdetails.UsernameNotFoundException;
12 | import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
13 | import org.springframework.security.crypto.password.PasswordEncoder;
14 | import org.springframework.util.StringUtils;
15 |
16 | import java.util.ArrayList;
17 | import java.util.Collections;
18 |
19 | @Configuration
20 | @EnableWebSecurity
21 | public class SecurityConfig extends WebSecurityConfigurerAdapter {
22 |
23 | @Bean
24 | public PasswordEncoder passwordEncoder() {
25 | return new BCryptPasswordEncoder();
26 | }
27 |
28 | @Bean
29 | public AuthenticationManager authenticationManager() throws Exception {
30 | return super.authenticationManager();
31 | }
32 |
33 | @Override
34 | protected void configure(AuthenticationManagerBuilder auth) throws Exception {
35 | auth.inMemoryAuthentication()
36 | .withUser("hellxz")
37 | .password(passwordEncoder().encode("xyz"))
38 | .authorities(new ArrayList<>(0));
39 | }
40 |
41 | @Override
42 | protected void configure(HttpSecurity http) throws Exception {
43 | //所有请求必须认证
44 | http.authorizeRequests().anyRequest().authenticated();
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/password/password-authorization-server/src/main/resources/application.properties:
--------------------------------------------------------------------------------
1 | server.port=8080
--------------------------------------------------------------------------------
/password/password-resource-server/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 | password
7 | com.github.hellxz
8 | 0.0.1-SNAPSHOT
9 |
10 | 4.0.0
11 |
12 | password-resource-server
13 |
14 |
15 |
--------------------------------------------------------------------------------
/password/password-resource-server/src/main/java/com/github/hellxz/oauth2/PasswordResourceApp.java:
--------------------------------------------------------------------------------
1 | package com.github.hellxz.oauth2;
2 |
3 | import org.springframework.boot.SpringApplication;
4 | import org.springframework.boot.autoconfigure.SpringBootApplication;
5 |
6 | @SpringBootApplication
7 | public class PasswordResourceApp {
8 | public static void main(String[] args) {
9 | SpringApplication.run(PasswordResourceApp.class, args);
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/password/password-resource-server/src/main/java/com/github/hellxz/oauth2/config/ResourceServerConfig.java:
--------------------------------------------------------------------------------
1 | package com.github.hellxz.oauth2.config;
2 |
3 | import org.springframework.context.annotation.Bean;
4 | import org.springframework.context.annotation.Configuration;
5 | import org.springframework.security.config.annotation.web.builders.HttpSecurity;
6 | import org.springframework.security.config.http.SessionCreationPolicy;
7 | import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
8 | import org.springframework.security.crypto.password.PasswordEncoder;
9 | import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
10 | import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
11 | import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
12 | import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer;
13 | import org.springframework.security.oauth2.provider.token.RemoteTokenServices;
14 | import sun.misc.Resource;
15 |
16 | import java.rmi.Remote;
17 |
18 | @Configuration
19 | @EnableResourceServer
20 | public class ResourceServerConfig extends ResourceServerConfigurerAdapter {
21 | @Bean
22 | public RemoteTokenServices remoteTokenServices() {
23 | final RemoteTokenServices tokenServices = new RemoteTokenServices();
24 | tokenServices.setClientId("client-a");
25 | tokenServices.setClientSecret("client-a-secret");
26 | tokenServices.setCheckTokenEndpointUrl("http://localhost:8080/oauth/check_token");
27 | return tokenServices;
28 | }
29 |
30 | @Override
31 | public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
32 | resources.stateless(true);
33 | }
34 |
35 | @Override
36 | public void configure(HttpSecurity http) throws Exception {
37 | //session创建策略
38 | http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED);
39 | //所有请求需要认证
40 | http.authorizeRequests().anyRequest().authenticated();
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/password/password-resource-server/src/main/java/com/github/hellxz/oauth2/web/controller/ResourceController.java:
--------------------------------------------------------------------------------
1 | package com.github.hellxz.oauth2.web.controller;
2 |
3 | import com.github.hellxz.oauth2.web.vo.UserVO;
4 | import org.slf4j.Logger;
5 | import org.slf4j.LoggerFactory;
6 | import org.springframework.security.core.context.SecurityContextHolder;
7 | import org.springframework.web.bind.annotation.GetMapping;
8 | import org.springframework.web.bind.annotation.PathVariable;
9 | import org.springframework.web.bind.annotation.RestController;
10 |
11 | @RestController
12 | public class ResourceController {
13 | private static final Logger log = LoggerFactory.getLogger(ResourceController.class);
14 |
15 | @GetMapping("/user/{username}")
16 | public UserVO user(@PathVariable String username){
17 | log.info("{}", SecurityContextHolder.getContext().getAuthentication());
18 | return new UserVO(username, username + "@foxmail.com");
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/password/password-resource-server/src/main/java/com/github/hellxz/oauth2/web/vo/UserVO.java:
--------------------------------------------------------------------------------
1 | package com.github.hellxz.oauth2.web.vo;
2 |
3 | public class UserVO {
4 | private String username;
5 | private String email;
6 |
7 | public UserVO(String username, String email) {
8 | this.username = username;
9 | this.email = email;
10 | }
11 |
12 | public String getUsername() {
13 | return username;
14 | }
15 |
16 | public void setUsername(String username) {
17 | this.username = username;
18 | }
19 |
20 | public String getEmail() {
21 | return email;
22 | }
23 |
24 | public void setEmail(String email) {
25 | this.email = email;
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/password/password-resource-server/src/main/resources/application.properties:
--------------------------------------------------------------------------------
1 | server.port=8081
--------------------------------------------------------------------------------
/password/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 | spring-security-oauth2-learn
7 | com.github.hellxz
8 | 0.0.1-SNAPSHOT
9 |
10 | 4.0.0
11 |
12 | password
13 | pom
14 |
15 | password-authorization-server
16 | password-resource-server
17 |
18 |
19 |
20 |
21 | org.springframework.security.oauth
22 | spring-security-oauth2
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/pictures/encoded-jwt3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hellxz/spring-security-oauth2-learn/f8c9843f70108fab99e888da8acd780ccace1818/pictures/encoded-jwt3.png
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | 4.0.0
5 |
6 | authorization-code
7 | implicit
8 | password
9 | client-credentials
10 | jwt
11 | redis-token-saved
12 | uaa-interface-adapter-demo
13 |
14 |
15 | org.springframework.boot
16 | spring-boot-starter-parent
17 | 2.2.1.RELEASE
18 |
19 |
20 | com.github.hellxz
21 | spring-security-oauth2-learn
22 | 0.0.1-SNAPSHOT
23 | pom
24 | spring-security-oauth2-learn
25 | Spring Security OAuth2 Four Pattern Demo
26 |
27 |
28 | 1.8
29 | 2.4.0.RELEASE
30 | 1.1.0.RELEASE
31 |
32 | 1.2.79
33 | 1.13
34 | 3.9
35 |
36 | 8.0.28
37 |
38 | 2.2.10.RELEASE
39 | 2.11.0
40 |
41 | 5.2.3.RELEASE
42 | 5.2.3.RELEASE
43 | 5.2.3.RELEASE
44 |
45 |
46 |
47 |
48 |
49 | org.springframework.boot
50 | spring-boot-dependencies
51 | 2.2.1.RELEASE
52 |
53 |
54 | org.springframework.security.oauth
55 | spring-security-oauth2
56 | ${spring-security-oauth2.version}
57 |
58 |
59 | org.springframework.security
60 | spring-security-jwt
61 | ${spring-security-jwt.version}
62 |
63 |
64 | com.alibaba
65 | fastjson
66 | ${fastjson.version}
67 |
68 |
69 | commons-codec
70 | commons-codec
71 | ${commons-codec.version}
72 |
73 |
74 | org.apache.commons
75 | commons-lang3
76 | ${commons-lang3.version}
77 |
78 |
79 | mysql
80 | mysql-connector-java
81 | ${mysql.version}
82 |
83 |
84 | org.springframework.cloud
85 | spring-cloud-starter-openfeign
86 | ${spring-cloud-starter-openfeign.version}
87 |
88 |
89 | commons-io
90 | commons-io
91 |
92 |
93 |
94 |
95 | commons-io
96 | commons-io
97 | ${commons-io.version}
98 |
99 |
100 |
101 |
102 |
103 |
104 | org.springframework.boot
105 | spring-boot-starter-security
106 |
107 |
108 |
109 | org.springframework.boot
110 | spring-boot-starter-web
111 |
112 |
113 | org.springframework.security
114 | spring-security-test
115 | test
116 |
117 |
118 | org.springframework.boot
119 | spring-boot-starter-test
120 |
121 |
122 |
123 |
124 |
125 |
126 | org.springframework.boot
127 | spring-boot-maven-plugin
128 |
129 |
130 |
131 |
132 |
133 |
--------------------------------------------------------------------------------
/redis-token-saved/README.md:
--------------------------------------------------------------------------------
1 | # redis-token-saved
2 | ## 简单说明
3 | 此模式用于演示存储access_token\refresh_token到redis中,
4 | 并且提供使用redis来校验token是否正确的资源服务器配置
--------------------------------------------------------------------------------
/redis-token-saved/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 | spring-security-oauth2-learn
7 | com.github.hellxz
8 | 0.0.1-SNAPSHOT
9 |
10 | 4.0.0
11 |
12 | redis-token-saved
13 | pom
14 |
15 | redis-token-saved-authorization-server
16 | redis-token-saved-resource-server
17 |
18 |
19 |
20 |
21 | org.springframework.security.oauth
22 | spring-security-oauth2
23 |
24 |
25 | org.springframework.boot
26 | spring-boot-starter-data-redis
27 |
28 |
29 |
--------------------------------------------------------------------------------
/redis-token-saved/redis-token-saved-authorization-server/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 | redis-token-saved
7 | com.github.hellxz
8 | 0.0.1-SNAPSHOT
9 |
10 | 4.0.0
11 |
12 | redis-token-saved-authorization-server
13 |
14 |
15 |
16 | com.alibaba
17 | fastjson
18 |
19 |
20 |
--------------------------------------------------------------------------------
/redis-token-saved/redis-token-saved-authorization-server/src/main/java/com/github/hellxz/oauth2/RedisAuthorizationServer.java:
--------------------------------------------------------------------------------
1 | package com.github.hellxz.oauth2;
2 |
3 | import org.springframework.boot.SpringApplication;
4 | import org.springframework.boot.autoconfigure.SpringBootApplication;
5 |
6 | /**
7 | * redis作为token存储的授权server
8 | */
9 | @SpringBootApplication
10 | public class RedisAuthorizationServer {
11 |
12 | public static void main(String[] args) {
13 | SpringApplication.run(RedisAuthorizationServer.class, args);
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/redis-token-saved/redis-token-saved-authorization-server/src/main/java/com/github/hellxz/oauth2/config/AuthorizationConfig.java:
--------------------------------------------------------------------------------
1 | package com.github.hellxz.oauth2.config;
2 |
3 | import org.springframework.beans.factory.annotation.Autowired;
4 | import org.springframework.context.annotation.Bean;
5 | import org.springframework.context.annotation.Configuration;
6 | import org.springframework.data.redis.connection.RedisConnectionFactory;
7 | import org.springframework.security.authentication.AuthenticationManager;
8 | import org.springframework.security.core.userdetails.UserDetailsService;
9 | import org.springframework.security.crypto.password.PasswordEncoder;
10 | import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
11 | import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
12 | import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
13 | import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
14 | import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
15 | import org.springframework.security.oauth2.provider.token.DefaultTokenServices;
16 | import org.springframework.security.oauth2.provider.token.TokenStore;
17 | import org.springframework.security.oauth2.provider.token.store.redis.RedisTokenStore;
18 |
19 | @Configuration
20 | @EnableAuthorizationServer
21 | public class AuthorizationConfig extends AuthorizationServerConfigurerAdapter {
22 |
23 | /**
24 | * redis工厂,默认使用lettue
25 | */
26 | @Autowired
27 | public RedisConnectionFactory redisConnectionFactory;
28 |
29 | /**
30 | * 用户认证管理器
31 | */
32 | @Autowired
33 | public AuthenticationManager authenticationManager;
34 |
35 | /**
36 | * 用户服务
37 | */
38 | @Autowired
39 | public UserDetailsService userDetailsService;
40 |
41 | /**
42 | * 密码加密器
43 | */
44 | @Autowired
45 | private PasswordEncoder passwordEncoder;
46 |
47 | /**
48 | * 授权服务安全配置,主要用于放行客户端访问授权服务接口
49 | *
50 | * @param security AuthorizationServerSecurityConfigurer
51 | * @throws Exception 异常
52 | */
53 | @Override
54 | public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
55 | //允许客户端表单提交
56 | security.allowFormAuthenticationForClients()
57 | //客户端校验token访问许可
58 | .checkTokenAccess("permitAll()")
59 | //客户端token调用许可
60 | .tokenKeyAccess("permitAll()");
61 | }
62 |
63 | /**
64 | * 客户端信息配置,可配置多个客户端,这里可以使用配置文件进行代替
65 | *
66 | * @param clients 客户端设置
67 | * @throws Exception 异常
68 | */
69 | @Override
70 | public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
71 | clients.inMemory()
72 | .withClient("client-a")
73 | .secret(passwordEncoder.encode("client-a-secret"))
74 | .redirectUris("http://localhost:9001/callback")
75 | //支持 授权码、密码两种授权模式,支持刷新token功能
76 | .authorizedGrantTypes("authorization_code", "password", "refresh_token");
77 | }
78 |
79 | /**
80 | * 配置端点
81 | *
82 | * @param endpoints 端点
83 | * @throws Exception 异常
84 | */
85 | @Override
86 | public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
87 | //配置认证管理器
88 | endpoints.authenticationManager(authenticationManager)
89 | //配置用户服务
90 | .userDetailsService(userDetailsService)
91 | //配置token存储的服务与位置
92 | .tokenServices(tokenService())
93 | .tokenStore(tokenStore());
94 | }
95 |
96 | @Bean
97 | public TokenStore tokenStore() {
98 | //使用redis存储token
99 | RedisTokenStore redisTokenStore = new RedisTokenStore(redisConnectionFactory);
100 | //设置redis token存储中的前缀
101 | redisTokenStore.setPrefix("auth-token:");
102 | return redisTokenStore;
103 | }
104 |
105 | @Bean
106 | public DefaultTokenServices tokenService() {
107 | DefaultTokenServices tokenServices = new DefaultTokenServices();
108 | //配置token存储
109 | tokenServices.setTokenStore(tokenStore());
110 | //开启支持refresh_token,此处如果之前没有配置,启动服务后再配置重启服务,可能会导致不返回token的问题,解决方式:清除redis对应token存储
111 | tokenServices.setSupportRefreshToken(true);
112 | //复用refresh_token
113 | tokenServices.setReuseRefreshToken(true);
114 | //token有效期,设置12小时
115 | tokenServices.setAccessTokenValiditySeconds(12 * 60 * 60);
116 | //refresh_token有效期,设置一周
117 | tokenServices.setRefreshTokenValiditySeconds(7 * 24 * 60 * 60);
118 | return tokenServices;
119 | }
120 | }
121 |
--------------------------------------------------------------------------------
/redis-token-saved/redis-token-saved-authorization-server/src/main/java/com/github/hellxz/oauth2/config/SecurityConfig.java:
--------------------------------------------------------------------------------
1 | package com.github.hellxz.oauth2.config;
2 |
3 | import org.springframework.context.annotation.Bean;
4 | import org.springframework.context.annotation.Configuration;
5 | import org.springframework.http.HttpMethod;
6 | import org.springframework.security.authentication.AuthenticationManager;
7 | import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
8 | import org.springframework.security.config.annotation.web.builders.HttpSecurity;
9 | import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
10 | import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
11 | import org.springframework.security.core.authority.AuthorityUtils;
12 | import org.springframework.security.core.userdetails.UserDetailsService;
13 | import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
14 | import org.springframework.security.crypto.password.PasswordEncoder;
15 |
16 | @Configuration
17 | @EnableWebSecurity
18 | public class SecurityConfig extends WebSecurityConfigurerAdapter {
19 |
20 | @Bean
21 | public PasswordEncoder passwordEncoder() {
22 | return new BCryptPasswordEncoder();
23 | }
24 |
25 | /**
26 | * 配置认证管理器信息,这里可以使用UserDetailsService实现类来提供用户信息,或Provider+UserDetailsService
27 | *
28 | * @param auth 认证管理器配置
29 | * @throws Exception 异常
30 | */
31 | @Override
32 | protected void configure(AuthenticationManagerBuilder auth) throws Exception {
33 | //@formatter:off
34 | auth.inMemoryAuthentication()
35 | .withUser("hellxz")
36 | .password(passwordEncoder().encode("test"))
37 | .authorities(AuthorityUtils.createAuthorityList("all"));
38 | //@formatter:on
39 | }
40 |
41 | /**
42 | * 配置http访问控制
43 | *
44 | * @param http http安全配置
45 | * @throws Exception 异常
46 | */
47 | @Override
48 | protected void configure(HttpSecurity http) throws Exception {
49 | http.authorizeRequests()
50 | //放行options方法请求
51 | .antMatchers(HttpMethod.OPTIONS).permitAll()
52 | .anyRequest().authenticated()
53 | .and()
54 | .csrf().disable();
55 | }
56 |
57 | @Bean
58 | public AuthenticationManager authenticationManager() throws Exception {
59 | return super.authenticationManager();
60 | }
61 |
62 | @Bean
63 | public UserDetailsService userDetailsService() {
64 | return super.userDetailsService();
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/redis-token-saved/redis-token-saved-authorization-server/src/main/resources/application.yml:
--------------------------------------------------------------------------------
1 | server:
2 | port: 8080
3 |
4 | spring:
5 | redis:
6 | host: 127.0.0.1
7 | port: 6379
8 | password: 123
9 | database: 0
10 |
--------------------------------------------------------------------------------
/redis-token-saved/redis-token-saved-authorization-server/src/test/java/com/github/hellxz/auth2/RedisTokenSavedServerTest.java:
--------------------------------------------------------------------------------
1 | package com.github.hellxz.auth2;
2 |
3 | import com.alibaba.fastjson.JSONObject;
4 | import com.github.hellxz.oauth2.RedisAuthorizationServer;
5 | import org.junit.Before;
6 | import org.junit.Test;
7 | import org.junit.runner.RunWith;
8 | import org.slf4j.Logger;
9 | import org.slf4j.LoggerFactory;
10 | import org.springframework.beans.factory.annotation.Autowired;
11 | import org.springframework.boot.test.context.SpringBootTest;
12 | import org.springframework.http.MediaType;
13 | import org.springframework.security.web.FilterChainProxy;
14 | import org.springframework.test.context.junit4.SpringRunner;
15 | import org.springframework.test.web.servlet.MockMvc;
16 | import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
17 | import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
18 | import org.springframework.test.web.servlet.setup.MockMvcBuilders;
19 | import org.springframework.util.StringUtils;
20 | import org.springframework.web.context.WebApplicationContext;
21 |
22 | import java.nio.charset.StandardCharsets;
23 | import java.util.Base64;
24 |
25 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
26 |
27 | @RunWith(SpringRunner.class)
28 | @SpringBootTest(classes = {RedisAuthorizationServer.class})
29 | public class RedisTokenSavedServerTest {
30 | private static final Logger log = LoggerFactory.getLogger(RedisTokenSavedServerTest.class);
31 |
32 | @Autowired
33 | private WebApplicationContext context;
34 | @Autowired
35 | private FilterChainProxy springSecurityFilterChain;
36 | private MockMvc mockMvc;
37 |
38 | @Before
39 | public void init(){
40 | //初始化web上下文,需要包含spring security filter chain
41 | mockMvc = MockMvcBuilders.webAppContextSetup(context).addFilter(springSecurityFilterChain).build();
42 | }
43 |
44 | @Test
45 | public void getAccessTokenTest() throws Exception {
46 | MockHttpServletRequestBuilder request = MockMvcRequestBuilders.post("http://localhost:8080/oauth/token")
47 | .header("Authorization", "Basic "
48 | + Base64.getEncoder().encodeToString("client-a:client-a-secret".getBytes(StandardCharsets.UTF_8)))
49 | .accept(MediaType.APPLICATION_JSON)
50 | .contentType(MediaType.APPLICATION_FORM_URLENCODED_VALUE)
51 | .param("username", "hellxz")
52 | .param("password", "test")
53 | .param("grant_type", "password")
54 | .param("scope", "all");
55 | String result = mockMvc.perform(request)
56 | .andExpect(status().is2xxSuccessful())
57 | .andReturn().getResponse().getContentAsString();
58 | if(!StringUtils.isEmpty(result)){
59 | log.info(result);
60 | }
61 | }
62 |
63 | @Test
64 | public void checkTokenTest() throws Exception{
65 | MockHttpServletRequestBuilder getAccessTokenRequest = MockMvcRequestBuilders.post("http://localhost:8080/oauth/token")
66 | .header("Authorization", "Basic "
67 | + Base64.getEncoder().encodeToString("client-a:client-a-secret".getBytes(StandardCharsets.UTF_8)))
68 | .accept(MediaType.APPLICATION_JSON)
69 | .contentType(MediaType.APPLICATION_FORM_URLENCODED_VALUE)
70 | .param("username", "hellxz")
71 | .param("password", "test")
72 | .param("grant_type", "password")
73 | .param("scope", "all");
74 | String accessTokenJson = mockMvc.perform(getAccessTokenRequest)
75 | .andExpect(status().is2xxSuccessful())
76 | .andReturn().getResponse().getContentAsString();
77 |
78 | JSONObject jsonObject = JSONObject.parseObject(accessTokenJson);
79 | MockHttpServletRequestBuilder checkTokenRequest = MockMvcRequestBuilders.post("http://localhost:8080/oauth/check_token")
80 | .header("Authorization", "Basic "
81 | + Base64.getEncoder().encodeToString("client-a:client-a-secret".getBytes(StandardCharsets.UTF_8)))
82 | .accept(MediaType.APPLICATION_JSON)
83 | .contentType(MediaType.APPLICATION_FORM_URLENCODED)
84 | .param("token", jsonObject.getString("access_token"));
85 | String responseBody = mockMvc.perform(checkTokenRequest)
86 | .andExpect(status().is2xxSuccessful())
87 | .andReturn().getResponse().getContentAsString();
88 | if(!StringUtils.isEmpty(responseBody)){
89 | log.info(responseBody);
90 | }
91 | }
92 |
93 | @Test
94 | public void refreshTokenTest() throws Exception {
95 | MockHttpServletRequestBuilder getAccessTokenRequest = MockMvcRequestBuilders.post("http://localhost:8080/oauth/token")
96 | .header("Authorization", "Basic "
97 | + Base64.getEncoder().encodeToString("client-a:client-a-secret".getBytes(StandardCharsets.UTF_8)))
98 | .accept(MediaType.APPLICATION_JSON)
99 | .contentType(MediaType.APPLICATION_FORM_URLENCODED_VALUE)
100 | .param("username", "hellxz")
101 | .param("password", "test")
102 | .param("grant_type", "password")
103 | .param("scope", "all");
104 | String accessTokenJson = mockMvc.perform(getAccessTokenRequest)
105 | .andExpect(status().is2xxSuccessful())
106 | .andReturn().getResponse().getContentAsString();
107 |
108 | JSONObject jsonObject = JSONObject.parseObject(accessTokenJson);
109 | MockHttpServletRequestBuilder request = MockMvcRequestBuilders.post("http://localhost:8080/oauth/token")
110 | .header("Authorization", "Basic "
111 | + Base64.getEncoder().encodeToString("client-a:client-a-secret".getBytes(StandardCharsets.UTF_8)))
112 | .accept(MediaType.APPLICATION_JSON)
113 | .contentType(MediaType.APPLICATION_FORM_URLENCODED)
114 | .param("refresh_token", jsonObject.getString("refresh_token"))
115 | .param("grant_type", "refresh_token")
116 | .param("scope", "all");
117 | String tokenJson = mockMvc.perform(request)
118 | .andExpect(status().is2xxSuccessful())
119 | .andReturn().getResponse().getContentAsString();
120 | if(!StringUtils.isEmpty(tokenJson)){
121 | log.info(tokenJson);
122 | }
123 | }
124 |
125 | // @Test
126 | // public void revokeTokenTest() throws Exception {
127 | // MockHttpServletRequestBuilder getAccessTokenRequest = MockMvcRequestBuilders.post("http://localhost:8080/oauth/token")
128 | // .header("Authorization", "Basic "
129 | // + Base64.getEncoder().encodeToString("client-a:client-a-secret".getBytes(StandardCharsets.UTF_8)))
130 | // .accept(MediaType.APPLICATION_JSON)
131 | // .contentType(MediaType.APPLICATION_FORM_URLENCODED_VALUE)
132 | // .param("username", "hellxz")
133 | // .param("password", "test")
134 | // .param("grant_type", "password")
135 | // .param("scope", "all");
136 | // String accessTokenJson = mockMvc.perform(getAccessTokenRequest)
137 | // .andExpect(status().is2xxSuccessful())
138 | // .andReturn().getResponse().getContentAsString();
139 | //
140 | // JSONObject jsonObject = JSONObject.parseObject(accessTokenJson);
141 | // MockHttpServletRequestBuilder request = MockMvcRequestBuilders.post("http://localhost:8080/logout")
142 | // .header("Authorization", "Bearer " + jsonObject.getString("access_token"))
143 | // .accept(MediaType.APPLICATION_JSON)
144 | // .contentType(MediaType.APPLICATION_FORM_URLENCODED);
145 | // String revokeResult = mockMvc.perform(request)
146 | // .andExpect(status().is2xxSuccessful())
147 | // .andReturn().getResponse().getContentAsString();
148 | // if(!StringUtils.isEmpty(revokeResult)){
149 | // log.info(revokeResult);
150 | // }
151 | // }
152 |
153 | }
154 |
--------------------------------------------------------------------------------
/redis-token-saved/redis-token-saved-resource-server/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 | redis-token-saved
7 | com.github.hellxz
8 | 0.0.1-SNAPSHOT
9 |
10 | 4.0.0
11 |
12 | redis-token-saved-resource-server
13 |
--------------------------------------------------------------------------------
/redis-token-saved/redis-token-saved-resource-server/src/main/java/com/github/hellxz/oauth2/RedisResourceServer.java:
--------------------------------------------------------------------------------
1 | package com.github.hellxz.oauth2;
2 |
3 | import org.springframework.boot.SpringApplication;
4 | import org.springframework.boot.autoconfigure.SpringBootApplication;
5 |
6 | /**
7 | * 使用redis作为token存储的资源服务器,这里不使用调用授权服务器的方式去校验资源,只需要从redis中取token进行判断即可
8 | */
9 | @SpringBootApplication
10 | public class RedisResourceServer {
11 | public static void main(String[] args) {
12 | SpringApplication.run(RedisResourceServer.class, args);
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/redis-token-saved/redis-token-saved-resource-server/src/main/java/com/github/hellxz/oauth2/config/ResourceServerConfig.java:
--------------------------------------------------------------------------------
1 | package com.github.hellxz.oauth2.config;
2 |
3 | import org.springframework.beans.factory.annotation.Autowired;
4 | import org.springframework.context.annotation.Bean;
5 | import org.springframework.context.annotation.Configuration;
6 | import org.springframework.data.redis.connection.RedisConnectionFactory;
7 | import org.springframework.security.config.annotation.web.builders.HttpSecurity;
8 | import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
9 | import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
10 | import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer;
11 | import org.springframework.security.oauth2.provider.token.store.redis.RedisTokenStore;
12 |
13 | @Configuration
14 | @EnableResourceServer
15 | public class ResourceServerConfig extends ResourceServerConfigurerAdapter {
16 |
17 | @Autowired
18 | private RedisConnectionFactory redisConnectionFactory;
19 |
20 | @Override
21 | public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
22 | //无状态
23 | resources.stateless(true);
24 | //设置token存储
25 | resources.tokenStore(tokenStore());
26 | }
27 |
28 | /**
29 | * 设置token存储,这一点配置要与授权服务器相一致
30 | */
31 | @Bean
32 | public RedisTokenStore tokenStore(){
33 | RedisTokenStore redisTokenStore = new RedisTokenStore(redisConnectionFactory);
34 | redisTokenStore.setPrefix("auth-token:");
35 | return redisTokenStore;
36 | }
37 |
38 | @Override
39 | public void configure(HttpSecurity http) throws Exception {
40 | http.csrf().disable()
41 | .authorizeRequests()
42 | .anyRequest().authenticated()
43 | .and()
44 | .httpBasic();
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/redis-token-saved/redis-token-saved-resource-server/src/main/java/com/github/hellxz/oauth2/web/controller/ResourceController.java:
--------------------------------------------------------------------------------
1 | package com.github.hellxz.oauth2.web.controller;
2 |
3 | import com.github.hellxz.oauth2.web.vo.UserVO;
4 | import org.slf4j.Logger;
5 | import org.slf4j.LoggerFactory;
6 | import org.springframework.security.core.context.SecurityContextHolder;
7 | import org.springframework.web.bind.annotation.GetMapping;
8 | import org.springframework.web.bind.annotation.PathVariable;
9 | import org.springframework.web.bind.annotation.RestController;
10 |
11 | @RestController
12 | public class ResourceController {
13 | private static final Logger log = LoggerFactory.getLogger(ResourceController.class);
14 |
15 | @GetMapping("/user/{username}")
16 | public UserVO user(@PathVariable String username){
17 | log.info("{}", SecurityContextHolder.getContext().getAuthentication());
18 | return new UserVO(username, username + "@foxmail.com");
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/redis-token-saved/redis-token-saved-resource-server/src/main/java/com/github/hellxz/oauth2/web/vo/UserVO.java:
--------------------------------------------------------------------------------
1 | package com.github.hellxz.oauth2.web.vo;
2 |
3 | public class UserVO {
4 | private String username;
5 | private String email;
6 |
7 | public UserVO(String username, String email) {
8 | this.username = username;
9 | this.email = email;
10 | }
11 |
12 | public String getUsername() {
13 | return username;
14 | }
15 |
16 | public void setUsername(String username) {
17 | this.username = username;
18 | }
19 |
20 | public String getEmail() {
21 | return email;
22 | }
23 |
24 | public void setEmail(String email) {
25 | this.email = email;
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/redis-token-saved/redis-token-saved-resource-server/src/main/resources/application.yml:
--------------------------------------------------------------------------------
1 | server:
2 | port: 8081
3 |
4 | spring:
5 | redis:
6 | host: 127.0.0.1
7 | port: 6379
8 | password: 123
9 | database: 0
10 |
--------------------------------------------------------------------------------
/uaa-interface-adapter-demo/README.md:
--------------------------------------------------------------------------------
1 | # uaa-interface-adapter-demo
2 | 使用OAuth2提供的工具类,在不重写源码的情况下,使用Api接口层面进行适配接口
3 | 暂适配了密码模式与客户端模式接口
4 |
5 | 使用的授权服务模式为jwt的`jwt-authorization-server`模块
--------------------------------------------------------------------------------
/uaa-interface-adapter-demo/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 | spring-security-oauth2-learn
7 | com.github.hellxz
8 | 0.0.1-SNAPSHOT
9 |
10 | 4.0.0
11 |
12 | uaa-interface-adapter-demo
13 |
14 |
15 | org.springframework.security.oauth
16 | spring-security-oauth2
17 |
18 |
19 | com.alibaba
20 | fastjson
21 |
22 |
23 | commons-codec
24 | commons-codec
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/uaa-interface-adapter-demo/src/main/java/com/github/hellxz/oauth2/demo/UaaAdapterApplication.java:
--------------------------------------------------------------------------------
1 | package com.github.hellxz.oauth2.demo;
2 |
3 | import org.springframework.boot.SpringApplication;
4 | import org.springframework.boot.autoconfigure.SpringBootApplication;
5 |
6 | @SpringBootApplication
7 | public class UaaAdapterApplication {
8 | public static void main(String[] args) {
9 | SpringApplication.run(UaaAdapterApplication.class, args);
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/uaa-interface-adapter-demo/src/main/java/com/github/hellxz/oauth2/demo/config/WebSecurityConfig.java:
--------------------------------------------------------------------------------
1 | package com.github.hellxz.oauth2.demo.config;
2 |
3 | import org.springframework.context.annotation.Configuration;
4 | import org.springframework.security.config.annotation.web.builders.HttpSecurity;
5 | import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
6 | import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
7 |
8 | @Configuration
9 | @EnableWebSecurity
10 | public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
11 | @Override
12 | protected void configure(HttpSecurity http) throws Exception {
13 | http.authorizeRequests()
14 | .antMatchers("/api/*/login").permitAll()
15 | .anyRequest().authenticated();
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/uaa-interface-adapter-demo/src/main/java/com/github/hellxz/oauth2/demo/controller/UaaAdapterController.java:
--------------------------------------------------------------------------------
1 | package com.github.hellxz.oauth2.demo.controller;
2 |
3 | import com.alibaba.fastjson.JSONObject;
4 | import com.github.hellxz.oauth2.demo.utils.Response;
5 | import org.apache.commons.codec.binary.Base64;
6 | import org.slf4j.Logger;
7 | import org.slf4j.LoggerFactory;
8 | import org.springframework.beans.factory.annotation.Value;
9 | import org.springframework.security.oauth2.client.resource.OAuth2AccessDeniedException;
10 | import org.springframework.security.oauth2.client.token.DefaultAccessTokenRequest;
11 | import org.springframework.security.oauth2.client.token.grant.client.ClientCredentialsAccessTokenProvider;
12 | import org.springframework.security.oauth2.client.token.grant.client.ClientCredentialsResourceDetails;
13 | import org.springframework.security.oauth2.client.token.grant.password.ResourceOwnerPasswordAccessTokenProvider;
14 | import org.springframework.security.oauth2.client.token.grant.password.ResourceOwnerPasswordResourceDetails;
15 | import org.springframework.security.oauth2.common.OAuth2AccessToken;
16 | import org.springframework.web.bind.annotation.GetMapping;
17 | import org.springframework.web.bind.annotation.RequestHeader;
18 | import org.springframework.web.bind.annotation.RequestParam;
19 | import org.springframework.web.bind.annotation.RestController;
20 |
21 | import java.nio.charset.StandardCharsets;
22 | import java.util.Arrays;
23 | import java.util.Collections;
24 |
25 | /**
26 | * 授权Api适配controller
27 | */
28 | @RestController
29 | @SuppressWarnings("deprecation")
30 | public class UaaAdapterController {
31 | private static final Logger log = LoggerFactory.getLogger(UaaAdapterController.class);
32 |
33 | @Value("${custom.uaa-uri}")
34 | String uaaUri;
35 |
36 | @GetMapping("/api/user/login")
37 | public Response userLogin(@RequestHeader("Authorization") String authorization,
38 | @RequestParam String username, @RequestParam String password) {
39 | ResourceOwnerPasswordAccessTokenProvider provider = new ResourceOwnerPasswordAccessTokenProvider();
40 | ResourceOwnerPasswordResourceDetails passwordResourceDetails =
41 | obtainPasswordResourceDetails(authorization, username, password);
42 | OAuth2AccessToken oAuth2AccessToken = null;
43 | try {
44 | oAuth2AccessToken = provider.obtainAccessToken(passwordResourceDetails,
45 | new DefaultAccessTokenRequest());
46 | } catch (OAuth2AccessDeniedException accessDeniedException) {
47 | log.error("获取访问token失败", accessDeniedException);
48 | return new Response().err("获取访问token失败", accessDeniedException.getStackTrace().toString());
49 | }
50 | return new Response().ok(oAuth2AccessToken);
51 | }
52 |
53 | @GetMapping("/api/client/login")
54 | public Response clientLogin(@RequestHeader("Authorization") String authorization){
55 | ClientCredentialsAccessTokenProvider clientCredentialsAccessTokenProvider = new ClientCredentialsAccessTokenProvider();
56 | ClientCredentialsResourceDetails clientCredentialsResourceDetails = obtainClientCredentialResourceDetails(authorization);
57 |
58 | OAuth2AccessToken oAuth2AccessToken = null;
59 | try{
60 | oAuth2AccessToken = clientCredentialsAccessTokenProvider.obtainAccessToken(
61 | clientCredentialsResourceDetails, new DefaultAccessTokenRequest());
62 | }catch(OAuth2AccessDeniedException accessDeniedException){
63 | log.error("获取访问token失败", accessDeniedException);
64 | return new Response().err("获取访问token失败", accessDeniedException.getStackTrace().toString());
65 | }
66 | return new Response().ok(oAuth2AccessToken);
67 | }
68 |
69 | private ResourceOwnerPasswordResourceDetails obtainPasswordResourceDetails(
70 | String authorization, String username, String password) {
71 | ResourceOwnerPasswordResourceDetails passwordResourceDetails = new ResourceOwnerPasswordResourceDetails();
72 | passwordResourceDetails.setUsername(username);
73 | passwordResourceDetails.setPassword(password);
74 | JSONObject clientInfo = getClientInfoFromAuthorization(authorization);
75 | passwordResourceDetails.setClientId(clientInfo.getString("clientId"));
76 | passwordResourceDetails.setClientSecret(clientInfo.getString("clientSecret"));
77 | String[] scopes = {"users"};
78 | passwordResourceDetails.setScope(Arrays.asList(scopes));
79 | passwordResourceDetails.setAccessTokenUri(uaaUri);
80 | return passwordResourceDetails;
81 | }
82 |
83 | private ClientCredentialsResourceDetails obtainClientCredentialResourceDetails(String authorization){
84 | ClientCredentialsResourceDetails clientCredentialsResourceDetails = new ClientCredentialsResourceDetails();
85 | JSONObject clientInfo = getClientInfoFromAuthorization(authorization);
86 | clientCredentialsResourceDetails.setClientId(clientInfo.getString("clientId"));
87 | clientCredentialsResourceDetails.setClientSecret(clientInfo.getString("clientSecret"));
88 | clientCredentialsResourceDetails.setScope(Collections.singletonList("service"));
89 | clientCredentialsResourceDetails.setAccessTokenUri(uaaUri);
90 | return clientCredentialsResourceDetails;
91 | }
92 |
93 | private JSONObject getClientInfoFromAuthorization(String authorization) {
94 | if(!authorization.toLowerCase().startsWith("basic")){
95 | throw new RuntimeException("解析请求头失败");
96 | }
97 | String basic = authorization.replace("Basic", "").trim();
98 | byte[] decode = Base64.decodeBase64(basic.getBytes(StandardCharsets.UTF_8));
99 | String contractStr = new String(decode);
100 | if (!contractStr.contains(":")){
101 | throw new RuntimeException("解析请求头失败");
102 | }
103 | String[] clientInfoArray = contractStr.split(":", 2);
104 | JSONObject json = new JSONObject();
105 | json.put("clientId", clientInfoArray[0]);
106 | json.put("clientSecret", clientInfoArray[1]);
107 | return json;
108 | }
109 | }
110 |
--------------------------------------------------------------------------------
/uaa-interface-adapter-demo/src/main/java/com/github/hellxz/oauth2/demo/utils/Response.java:
--------------------------------------------------------------------------------
1 | package com.github.hellxz.oauth2.demo.utils;
2 |
3 | /**
4 | * 响应工具类
5 | */
6 | public class Response {
7 | Integer code;
8 | String msg;
9 | T data;
10 |
11 | public Response() {
12 | }
13 |
14 | public Response(Integer code, String msg, T data) {
15 | this.code = code;
16 | this.msg = msg;
17 | this.data = data;
18 | }
19 |
20 | public Response(Integer code, String msg) {
21 | this.code = code;
22 | this.msg = msg;
23 | this.data = null;
24 | }
25 |
26 | public Response ok(String msg) {
27 | return new Response(200, msg);
28 | }
29 |
30 | public Response ok(T data) {
31 | return new Response<>(200, "成功", data);
32 | }
33 |
34 | public Response ok(String msg, T data) {
35 | return new Response<>(200, msg, data);
36 | }
37 |
38 | public Response err(String msg){
39 | return new Response<>(500, msg);
40 | }
41 |
42 | public Response err(Integer code, String msg){
43 | return new Response<>(code, msg);
44 | }
45 |
46 | public Response err(String msg, T data){
47 | return new Response<>(500, msg, data);
48 | }
49 |
50 | public Response err(Integer code, String msg, T data){
51 | return new Response<>(code, msg, data);
52 | }
53 |
54 | public Integer getCode() {
55 | return code;
56 | }
57 |
58 | public void setCode(Integer code) {
59 | this.code = code;
60 | }
61 |
62 | public String getMsg() {
63 | return msg;
64 | }
65 |
66 | public void setMsg(String msg) {
67 | this.msg = msg;
68 | }
69 |
70 | public T getData() {
71 | return data;
72 | }
73 |
74 | public void setData(T data) {
75 | this.data = data;
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/uaa-interface-adapter-demo/src/main/resources/application.yml:
--------------------------------------------------------------------------------
1 | server:
2 | port: 9001
3 | custom:
4 | uaa-uri: http://localhost:8080/oauth/token
--------------------------------------------------------------------------------