# spring-security-oauth2 **Repository Path**: lycnihao/spring-security-oauth2 ## Basic Information - **Project Name**: spring-security-oauth2 - **Description**: Spring Security OAuth2 Authorization Server学习(已过时 不是最新版本) - **Primary Language**: Java - **License**: MIT - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 4 - **Forks**: 3 - **Created**: 2022-03-10 - **Last Updated**: 2023-06-30 ## Categories & Tags **Categories**: Uncategorized **Tags**: spring-security-oauth2, spring-security, OAuth2, OAuth2-Authorization-Server ## README > 先配置数据库连接参数,并导入oauth2相关表结构后再启动auth-server和security-auth服务,启动的时候CommandLineRunner会初始化数据库用户角色等信息。 > 授权码模式和客户端模式按照官方的测试案例所写的,没做过多的拓展。主要是密码模式,官方不再提供支持,但是有些场景又有用到,通过几天研究后发现这是可以自己实现的。 > 这部分代码在run.bottle.authserver.configuration.oauth2目录中,后面也拓展了一下客户端,可以通过用户与角色的关系来配置受保护的资源。当发起客户端携带token请求时,通过CustomJwtAuthenticationConverter转换器解析到jwt获取用户名与当前用户信息记录到上下文中,再通过ResourceVoter校验当前url与账号角色所拥有的资源是否一致,如果角色拥有该资源则校验通过否则校验失败 # 授权码模式: > 1. 请求http://localhost:9000/oauth2/authorize?client_id=login-client&redirect_uri=http://127.0.0.1:8080/authorized&response_type=code&scope=message.read 在URL参数中指定客户端 id、授权类型、请求 scope 等。 > 2. 登录user/password进行登录,确认授权后(通过配置客户端的clientSettings的requireAuthorizationConsent参数来开启是否同意授权页面) > 3. 登录成功后重定向到指定地址http://127.0.0.1:8080/authorized 其中包含`code`参数如下: http://127.0.0.1:8080/authorized?code=nGY7A92NawKJ-63873OGfChtAf4fn2Z6BoSud_HjB9YLeEDzuv9Cgojy4bQJG6RZ9SoFCL-1ZR2VOCinn4wzFN1k1wuHUYde4UqkJNwtwE5SaNv-XkZB6iWi1dRfV3x_ > 4. 获取code参数 > 5. 请求http://localhost:9000/oauth2/token 获取token,参数如下: ``` POST http://localhost:9000/oauth2/token Authorization: Basic bWVzc2FnaW5nLWNsaWVudDpzZWNyZXQ= Content-Type: application/x-www-form-urlencoded grant_type=client_credentials&scope=message.read ``` ![请求示例](docs/image/Snipaste_2022-03-13_18-20-27.png) ![请求示例](docs/image/Snipaste_2022-03-13_18-20-27.png) # 客户端模式: > 客户端模式就简单多了,只验证请求头中的授权信息和scope信息 ``` POST http://localhost:9000/oauth2/token Authorization: Basic bWVzc2FnaW5nLWNsaWVudDpzZWNyZXQ= Content-Type: application/x-www-form-urlencoded grant_type=authorization_code&code=nGY7A92NawKJ-63873OGfChtAf4fn2Z6BoSud_HjB9YLeEDzuv9Cgojy4bQJG6RZ9SoFCL-1ZR2VOCinn4wzFN1k1wuHUYde4UqkJNwtwE5SaNv-XkZB6iWi1dRfV3x_&redirect_uri=http://127.0.0.1:8080/authorized ``` ![请求示例](docs/image/Snipaste_2022-03-13_18-33-19.png) ![请求示例](docs/image/Snipaste_2022-03-13_18-39-17.png) # 密码模式: > 直接通过账号密码进行授权 ``` POST http://localhost:9000/oauth2/token Authorization: Basic dXNlci1jbGllbnQ6dXNlci1zZWNyZXQ= Accept-Language: zh_CN Content-Type: application/x-www-form-urlencoded grant_type=password&username=user&password=password ``` ![请求示例](docs/image/Snipaste_2022-03-24_16-54-27.png) ![请求示例](docs/image/Snipaste_2022-03-24_16-55-02.png) # 刷新令牌 > 密码模式的Access Token的有效期已设置30分钟(默认5分钟),Refresh Token为默认的60分钟,客户端凭证不返回刷新令牌 ``` POST http://localhost:9000/oauth2/token Authorization: Basic bWVzc2FnaW5nLWNsaWVudDpzZWNyZXQ= Content-Type: application/x-www-form-urlencoded grant_type=refresh_token&refresh_token=... ``` ![请求示例](docs/image/Snipaste_2022-04-06_00-17-29.png) # 撤销令牌 ``` POST http://localhost:9000/oauth2/revoke Authorization: Basic bWVzc2FnaW5nLWNsaWVudDpzZWNyZXQ= Content-Type: application/x-www-form-urlencoded # token_type_hint 参数可选 token_type_hint=access_token&token=... 或 token_type_hint=refresh_token&token=... ``` ![请求示例](docs/image/Snipaste_2022-04-12_00-47-38.png) # 获取令牌信息 ``` POST http://localhost:9000/oauth2/introspect Authorization: Basic bWVzc2FnaW5nLWNsaWVudDpzZWNyZXQ= Content-Type: application/x-www-form-urlencoded # token_type_hint 参数可选 token_type_hint=access_token&token=... 或 token_type_hint=refresh_token&token=... ``` ![请求示例](docs/image/Snipaste_2022-04-12_00-47-33.png) # 客户端请求示例 > 每个请求中设置请求头header中指定Authorization值为Bearer $TOKEN,$TOKEN取自上述授权成功返回的access_token。 ``` Authorization:Bearer eyJraWQiOiI4ZGNjYzIxZS1iMTQ5LTRkNjAtYjRmZC02ZWIzYzdiZWYwMjIiLCJhbGciOiJSUzI1NiJ9.eyJzdWIiOiJtZXNzYWdpbmctY2xpZW50IiwiYXVkIjoibWVzc2FnaW5nLWNsaWVudCIsIm5iZiI6MTY0NzE4NjM2MCwic2NvcGUiOlsibWVzc2FnZTpyZWFkIl0sImlzcyI6Imh0dHA6XC9cL2xvY2FsaG9zdDo5MDAwIiwiZXhwIjoxNjQ3MTg2NjYwLCJpYXQiOjE2NDcxODYzNjB9.ca6oclRcLmHq4r7aTgZjK8JyQwPzmE7QwKN3VQmlNdNsetIKCp7sZ1Fot0fJaYZ02MKz-quSuQxkGov18i8dIP7gOxlf0OqFmCF4N6Pcl356FGHMQcGEzg1PgK9mV9bJ5Iv-N5hYjVbhVlrA8WnmOrxT66tTdpV0H1WVg5RnY2Bc83qPqwpsYd6QzNCq2Moz9oLC3M5WePuhohWyKLjDstuM-sZcLx6gCGe3B62OIWxlwVeIy88MCAf2C96bRaE9S_vOGeoWOvkIQNJqUHJ9vcWlm2Iw8S5Bo1uXwkqYIXk1ZsMRof3T_ZYnQO1lAcj5Ojil7rqeFipECSxSUhlvtw ``` - localhost:8080 > 其中'messaging-client'是授权服务器返回的JWT中'sub'字段的值(这个接口可以匿名访问,可以不传Authorization) ![localhost:8080](docs/image/Snipaste_2022-03-13_23-54-54.png) - localhost:8080/message > scope为message.read可以访问 ![localhost:8080/message](docs/image/Snipaste_2022-03-14_00-01-23.png) - localhost:8080/message > scope为message.write可以访问 ![localhost:8080/message](docs/image/Snipaste_2022-03-14_00-01-48.png) PS: 由于password授权模式在OAuth 2.1 中已被弃用,所以spring-security-oauth2没有对password授权提供支持(隐式模式和密码模式都没有实施)。看[#349](https://github.com/spring-projects/spring-authorization-server/issues/349) , [#466](https://github.com/spring-projects/spring-authorization-server/issues/466) 虽然spring-security-oauth2没有对密码模式的支持,但是我们可以自己实现 # 参考 * Spring-Security-Samples - https://github.com/spring-projects/spring-security-samples * Spring-Authorization-Server - https://github.com/spring-projects/spring-authorization-server * support password grant - https://github.com/spring-projects/spring-authorization-server/pull/343