From 55d592292bd60b54087e5b0fc312bc772a077ded Mon Sep 17 00:00:00 2001
From: mkk JDK -- 1.7.0_40 Maven -- 3.1.0 JDK -- 1.8.0_40 Maven -- 3.6.0 MySQL -- 5.6.23-log
- Version: 0.3 [pending]
+ Version: 2.0.0 [pending]
升级使用Spring Boot (153) - 尝试添加并实现OIDC在 oauth2-shiro中 升级shiro, oltu版本
+ Version: 0.3 [finished]
+ (153) - 尝试添加并实现OIDC在 oauth2-shiro中[canceled] 2016-07-02 添加在线测试环境 2016-08-17 发布 0.2 版本 2017-01-21 加入到GitHub中, Git@OSC地址: http://git.oschina.net/mkk/oauth2-shiro 2020-07-05 开始2.0.0版本开发
-
主要技术及版本
- Spring -- 3.2.2.RELEASE
+ Spring Boot-- 2.3.1.RELEASE
oltu -- 1.0.2
@@ -35,8 +35,8 @@
开发环境
-
如何使用
@@ -239,8 +253,5 @@
- Date: 2016-07-16 / ------
+ Date: 2020-07-05 / ---
-
+ (152) - oltu版本升级到1.0.2 并完成测试.
+
+ Date: 2016-07-16 / 2018-10-17
+
+
@@ -179,6 +192,7 @@
(152) - oltu版本升级到1.0.2 并完成测试.(161) - 增加必要的代码注释与配置注释, 更易理解implicit模式不需要带上client_secret
若需更多的商业技术支持请联系 sz@qc8.com
- 或访问 http://monkeyk.com/kso/
-
-
oltu -- 1.0.2
- shiro -- 1.2.3
+ shiro -- 1.5.3
MySQL -- 5.6
升级使用Spring Boot
升级使用JDK 1.8, 日志框架升级使用log4j2
(153) - 尝试添加并实现OIDC在 oauth2-shiro中
升级shiro, oltu版本
升级shiro到1.5.3, oltu版本无变化
+ * Replace authz-context.xml + * + * @author Shengzhao Li + * @since 2.0.0 + */ +@Configuration +public class AuthzContextConfig { + + + /** + * 事务配置 + */ + @Bean + public TransactionManager transactionManager(DataSource dataSource) { + DataSourceTransactionManager transactionManager = new DataSourceTransactionManager(); + transactionManager.setDataSource(dataSource); + return transactionManager; + } + + + @Bean + public JdbcTemplate jdbcTemplate(DataSource dataSource) { + JdbcTemplate jdbcTemplate = new JdbcTemplate(); + jdbcTemplate.setDataSource(dataSource); + return jdbcTemplate; + } + + + /** + * AuthenticationId 的生成器 + */ + @Bean + public AuthenticationIdGenerator authenticationIdGenerator() { + return new DefaultAuthenticationIdGenerator(); + } + + /** + * 使用MD5 OAuthIssuer, 生成随机值,如 access_token, refresh_token + * 可根据需要扩展使用其他的实现 + */ + @Bean + public OAuthIssuer oAuthIssuer() { + MD5Generator md5Generator = new MD5Generator(); + return new OAuthIssuerImpl(md5Generator); + } + + +} diff --git a/authz/src/main/java/com/monkeyk/os/config/AuthzSecurityConfig.java b/authz/src/main/java/com/monkeyk/os/config/AuthzSecurityConfig.java new file mode 100644 index 0000000..3449eee --- /dev/null +++ b/authz/src/main/java/com/monkeyk/os/config/AuthzSecurityConfig.java @@ -0,0 +1,136 @@ +package com.monkeyk.os.config; + +import com.monkeyk.os.infrastructure.shiro.MkkJdbcRealm; +import org.apache.shiro.authc.credential.CredentialsMatcher; +import org.apache.shiro.authc.credential.HashedCredentialsMatcher; +import org.apache.shiro.cache.AbstractCacheManager; +import org.apache.shiro.cache.MemoryConstrainedCacheManager; +import org.apache.shiro.mgt.SecurityManager; +import org.apache.shiro.realm.AuthorizingRealm; +import org.apache.shiro.realm.Realm; +import org.apache.shiro.spring.web.ShiroFilterFactoryBean; +import org.apache.shiro.web.mgt.DefaultWebSecurityManager; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import javax.sql.DataSource; +import java.util.HashMap; +import java.util.Map; + +/** + * 2020/7/14 + *
+ * Replace authz-security.xml
+ *
+ * @author Shengzhao Li
+ * @since 2.0.0
+ */
+@Configuration
+public class AuthzSecurityConfig {
+
+ /*
+ * 这是一个标准的 SHIRO 安全配置
+ 注意OAuth的URL配置: /oauth/** = anon
+ *
+ * */
+
+
+ /**
+ * 使用MD5 进行密码的加密
+ */
+ @Bean
+ public CredentialsMatcher credentialsMatcher() {
+ HashedCredentialsMatcher credentialsMatcher = new HashedCredentialsMatcher();
+ credentialsMatcher.setHashAlgorithmName("MD5");
+// credentialsMatcher.setStoredCredentialsHexEncoded(false);
+ return credentialsMatcher;
+ }
+
+ /**
+ * 扩展的 SHIRO Realm
+ * 使用JDBC实现, 并添加 逻辑删除 (archived = 0) 的处理
+ */
+ @Bean
+ public AuthorizingRealm jdbcRealm(DataSource dataSource) {
+ MkkJdbcRealm realm = new MkkJdbcRealm();
+ realm.setName("jdbcRealm");
+ realm.setDataSource(dataSource);
+ realm.setCredentialsMatcher(credentialsMatcher());
+ realm.setPermissionsLookupEnabled(true);
+ return realm;
+ }
+
+ /**
+ * 使用基于内存的缓存 SHIRO 相关数据
+ */
+ @Bean
+ public AbstractCacheManager shiroCacheManager() {
+ return new MemoryConstrainedCacheManager();
+ }
+
+ /**
+ * SHIRO SecurityManager 配置
+ */
+ @Bean
+ public DefaultWebSecurityManager securityManager(Realm realm) {
+ DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
+ securityManager.setRealm(realm);
+ securityManager.setCacheManager(shiroCacheManager());
+ return securityManager;
+ }
+
+
+ /**
+ * SHIRO安全机制拦截器 Filter实现, 注意id必须与 web.xml 中的 shiroFilter 一致
+ */
+ @Bean
+ public ShiroFilterFactoryBean shiroFilter(SecurityManager securityManager) {
+ ShiroFilterFactoryBean factoryBean = new ShiroFilterFactoryBean();
+ factoryBean.setSecurityManager(securityManager);
+ factoryBean.setLoginUrl("/login");
+ factoryBean.setSuccessUrl("/index");
+ factoryBean.setUnauthorizedUrl("/unauthorized");
+ //权限控制
+ Map
+ * Replace web.xml
+ * mkk-servlet.xml
+ *
+ * @author Shengzhao Li
+ * @since 2.0.0
+ */
+@Configuration
+public class AuthzWebConfig {
+
+
+ /**
+ * 字符编码配置 UTF-8
+ */
+ @Bean
+ public FilterRegistrationBean encodingFilter() {
+ FilterRegistrationBean
oltu -- 1.0.2
- shiro -- 1.5.3
+ shiro -- 1.11.0
MySQL -- 5.6
diff --git a/authz/pom.xml b/authz/pom.xml
index c8c5a06..2ad9195 100644
--- a/authz/pom.xml
+++ b/authz/pom.xml
@@ -29,7 +29,7 @@
升级使用Spring Boot
升级使用JDK 1.8, 日志框架升级使用log4j2
升级使用JDK 1.8, 日志框架升级使用logback
(153) - 尝试添加并实现OIDC在 oauth2-shiro中
升级shiro到1.5.3, oltu版本无变化
使用grant_type=password方式来获取access_token
+ +
+ 请求URI: /oauth/token
POST
+
参数名 | +参数值 | +必须? | +备注 | +
---|---|---|---|
client_id | +{client_id} | +是 | ++ |
client_secret | +{client_secret} | +是 | ++ |
grant_type | +password | +是 | +固定值 | +
scope | +{scope} | +是 | +read or write | +
username | +{username} | +是 | +用户名 | +
password | +{password} | +是 | +用户密码 | +
+ http://localhost:8080/authz/oauth/token?client_id=OMN4XjXmJidyzhUGWVrk&client_secret=wzRBGCblLSD4Zzfb3gl3&grant_type=password&scope=read&username=test&password=test
+
+ 正常 [200]
+
+ {"token_type":"Bearer","expires_in":43199,"refresh_token":"a135278d0382260ab9afaea05e5cbb26","access_token":"81fab07a5c91bcd06f60419fb22ecc9f"}
+
+
+ 异常 [400]
+
+ {"error":"invalid_grant","error_description":"Bad credentials"}
+
+
使用grant_type=authorization_code 方式来获取access_token, 需要先获取code
+ +
+ 请求URI: /oauth/token
POST
+
参数名 | +参数值 | +必须? | +备注 | +
---|---|---|---|
client_id | +{client_id} | +是 | ++ |
client_secret | +{client_secret} | +是 | ++ |
grant_type | +authorization_code | +是 | +固定值 | +
code | +{code} | +是 | ++ |
redirect_uri | +{redirect_uri} | +是 | ++ |
+ http://localhost:8080/authz/oauth/token?client_id=OMN4XjXmJidyzhUGWVrk&client_secret=wzRBGCblLSD4Zzfb3gl3&grant_type=authorization_code&code=26964a1255766630a&redirect_uri=http://localhost:8080/authz/
+
+ 正常 [200]
+
+ {"token_type":"Bearer","expires_in":43199,"refresh_token":"8e91a56f53857688a3ffd8c7cfd311cf","access_token":"8bdaab126137049bd209631a23024f12"}
+
+
+ 异常 [400]
+
+ {"error":"invalid_grant","error_description":"Invalid code
+ '26964e42c667b5d42f89a1255766630a'"}
+
+
使用grant_type=client_credentials 方式来获取access_token, 不需要username, password, 不支持 + refresh_token
+ +
+ 请求URI: /oauth/token
POST
+
参数名 | +参数值 | +必须? | +备注 | +
---|---|---|---|
client_id | +{client_id} | +是 | ++ |
client_secret | +{client_secret} | +是 | ++ |
grant_type | +client_credentials | +是 | +固定值 | +
scope | +{scope} | +是 | +read or write | +
+ http://localhost:8080/authz/oauth/token?client_id=OMN4XjXmJidyzhUGWVrk&client_secret=wzRBGCblLSD4Zzfb3gl3&grant_type=client_credentials&scope=read
+
+ 正常 [200]
+
+ {"token_type":"Bearer","expires_in":19476,"access_token":"ee7c7d1bf0cea77a883a082cb7085b64"}
+
+
+ 异常 [401]
+
+ {"error":"invalid_client","error_description":"Invalid client_id
+ 'OMN4XjXmJidyzhUGWVrdk'"}
+
+
用于在access_token要过期时换取新的access_token (grant_type需要有refresh_token)
+ +
+ 请求URI: /oauth/token
POST
+
参数名 | +参数值 | +必须? | +备注 | +
---|---|---|---|
client_id | +{client_id} | +是 | ++ |
client_secret | +{client_secret} | +是 | ++ |
grant_type | +refresh_token | +是 | +固定值 | +
refresh_token | +{refresh_token} | +是 | ++ |
+ http://localhost:8080/authz/oauth/token?client_id=OMN4XjXmJidyzhUGWVrk&client_secret=wzRBGCblLSD4Zzfb3gl3&grant_type=refresh_token&refresh_token=8e91a56f53857688a3ffd8c7cfd311cf
+
+ 正常 [200]
+
+ {"token_type":"Bearer","expires_in":43199,"refresh_token":"a407f77b8269493433e0756aedabad66","access_token":"a9beb6b987b3365f9c2efc46e19b1f1a"}
+
+
+ 异常 [400]
+
+ {"error":"invalid_grant","error_description":"Invalid refresh_token:
+ 8e91a56f53857688a3ffd8c7cfd311cfss"}
+
+
获取当前系统时间, 需要access_token的 resource-id 为 mobile-resource 才能访问
+ +
+ 请求URI: /mobile/system_time
GET
+
参数名 | +参数值 | +必须? | +备注 | +
---|---|---|---|
无 | +
+ http://localhost:8080/rs/mobile/system_time?access_token=95c3afd44c5d87301dc3034b20b3fc75
+
+ 正常 [200]
+
+ {"time":1465560577614}
+
+
+ 异常 [401]
+
+ {"error":"invalid_token","error_description":"Invalid access_token:
+ 95c3afd44c5d87301dc3034b20b3fc75s"}
+
+
使用access_token获取用户信息, 需要access_token的 resource-id 为 os-resource 且用户Role包含 User + 才能访问
+ +
+ 请求URI: /rs/username
GET
+
参数名 | +参数值 | +必须? | +备注 | +
---|---|---|---|
无 | +
+ http://localhost:8080/rs/rs/username?access_token=95c3afd44c5d87301dc3034b20b3fc75
+
+ 正常 [200]
+
+ {"clientId":"WQlJ2ZZBV8iJGKnkqfdbgvfVgY3Cp17AEbMijnID","username":"xiaowang"}
+
+
+ 异常 [401]
+
+ {"error":"invalid_token","error_description":"Invalid client by token:
+ 95c3afd44c5d87301dc3034b20b3fc75"}
+
+
使用grant_type=password方式来获取access_token
+ +
+ 请求URI: /oauth/token
POST
+
参数名 | +参数值 | +必须? | +备注 | +
---|---|---|---|
client_id | +{client_id} | +是 | ++ |
client_secret | +{client_secret} | +是 | ++ |
grant_type | +password | +是 | +固定值 | +
scope | +{scope} | +是 | +read or write | +
username | +{username} | +是 | +用户名 | +
password | +{password} | +是 | +用户密码 | +
+ http://localhost:8080/authz/oauth/token?client_id=OMN4XjXmJidyzhUGWVrk&client_secret=wzRBGCblLSD4Zzfb3gl3&grant_type=password&scope=read&username=test&password=test
+
+ 正常 [200]
+
+ {"token_type":"Bearer","expires_in":43199,"refresh_token":"a135278d0382260ab9afaea05e5cbb26","access_token":"81fab07a5c91bcd06f60419fb22ecc9f"}
+
+
+ 异常 [400]
+
+ {"error":"invalid_grant","error_description":"Bad credentials"}
+
+
使用grant_type=authorization_code 方式来获取access_token, 需要先获取code
+ +
+ 请求URI: /oauth/token
POST
+
参数名 | +参数值 | +必须? | +备注 | +
---|---|---|---|
client_id | +{client_id} | +是 | ++ |
client_secret | +{client_secret} | +是 | ++ |
grant_type | +authorization_code | +是 | +固定值 | +
code | +{code} | +是 | ++ |
redirect_uri | +{redirect_uri} | +是 | ++ |
+ http://localhost:8080/authz/oauth/token?client_id=OMN4XjXmJidyzhUGWVrk&client_secret=wzRBGCblLSD4Zzfb3gl3&grant_type=authorization_code&code=26964a1255766630a&redirect_uri=http://localhost:8080/authz/
+
+ 正常 [200]
+
+ {"token_type":"Bearer","expires_in":43199,"refresh_token":"8e91a56f53857688a3ffd8c7cfd311cf","access_token":"8bdaab126137049bd209631a23024f12"}
+
+
+ 异常 [400]
+
+ {"error":"invalid_grant","error_description":"Invalid code
+ '26964e42c667b5d42f89a1255766630a'"}
+
+
使用grant_type=token 方式来获取access_token, implicit模式; 需要登录
+ +
+ 请求URI: /oauth/token
GET
+
参数名 | +参数值 | +必须? | +备注 | +
---|---|---|---|
client_id | +{client_id} | +是 | ++ |
grant_type | +token | +是 | +固定值 | +
scope | +{scope} | +是 | +read or write | +
redirect_uri | +{redirect_uri} | +是 | ++ |
+ http://localhost:8080/authz/oauth/authorize?client_id=DYBeQ5lWFKyhY0TDSxxU&response_type=token&scope=read&redirect_uri=http://www.example.com
+
+ 正常 [200]
+
+ http://www.example.com#token_type=Bearer&expires_in=43199&access_token=fa3bb346a04e20431161771c0003c466
+
+
通过 redirect_uri的 URL hash 传递access_token信息
+使用grant_type=client_credentials 方式来获取access_token, 不需要username, password, 不支持 + refresh_token
+ +
+ 请求URI: /oauth/token
POST
+
参数名 | +参数值 | +必须? | +备注 | +
---|---|---|---|
client_id | +{client_id} | +是 | ++ |
client_secret | +{client_secret} | +是 | ++ |
grant_type | +client_credentials | +是 | +固定值 | +
scope | +{scope} | +是 | +read or write | +
+ http://localhost:8080/authz/oauth/token?client_id=OMN4XjXmJidyzhUGWVrk&client_secret=wzRBGCblLSD4Zzfb3gl3&grant_type=client_credentials&scope=read
+
+ 正常 [200]
+
+ {"token_type":"Bearer","expires_in":19476,"access_token":"ee7c7d1bf0cea77a883a082cb7085b64"}
+
+
+ 异常 [401]
+
+ {"error":"invalid_client","error_description":"Invalid client_id
+ 'OMN4XjXmJidyzhUGWVrdk'"}
+
+
用于在access_token要过期时换取新的access_token (grant_type需要有refresh_token)
+ +
+ 请求URI: /oauth/token
POST
+
参数名 | +参数值 | +必须? | +备注 | +
---|---|---|---|
client_id | +{client_id} | +是 | ++ |
client_secret | +{client_secret} | +是 | ++ |
grant_type | +refresh_token | +是 | +固定值 | +
refresh_token | +{refresh_token} | +是 | ++ |
+ http://localhost:8080/authz/oauth/token?client_id=OMN4XjXmJidyzhUGWVrk&client_secret=wzRBGCblLSD4Zzfb3gl3&grant_type=refresh_token&refresh_token=8e91a56f53857688a3ffd8c7cfd311cf
+
+ 正常 [200]
+
+ {"token_type":"Bearer","expires_in":43199,"refresh_token":"a407f77b8269493433e0756aedabad66","access_token":"a9beb6b987b3365f9c2efc46e19b1f1a"}
+
+
+ 异常 [400]
+
+ {"error":"invalid_grant","error_description":"Invalid refresh_token:
+ 8e91a56f53857688a3ffd8c7cfd311cfss"}
+
+
获取当前系统时间, 需要access_token的 resource-id 为 mobile-resource 才能访问
+ +
+ 请求URI: /mobile/system_time
GET
+
参数名 | +参数值 | +必须? | +备注 | +
---|---|---|---|
无 | +
+ http://localhost:8080/rs/mobile/system_time?access_token=95c3afd44c5d87301dc3034b20b3fc75
+
+ 正常 [200]
+
+ {"time":1465560577614}
+
+
+ 异常 [401]
+
+ {"error":"invalid_token","error_description":"Invalid access_token:
+ 95c3afd44c5d87301dc3034b20b3fc75s"}
+
+
使用access_token获取用户信息, 需要access_token的 resource-id 为 os-resource 且用户Role包含 User + 才能访问
+ +
+ 请求URI: /rs/username
GET
+
参数名 | +参数值 | +必须? | +备注 | +
---|---|---|---|
无 | +
+ http://localhost:8080/rs/rs/username?access_token=95c3afd44c5d87301dc3034b20b3fc75
+
+ 正常 [200]
+
+ {"clientId":"WQlJ2ZZBV8iJGKnkqfdbgvfVgY3Cp17AEbMijnID","username":"xiaowang"}
+
+
+ 异常 [401]
+
+ {"error":"invalid_token","error_description":"Invalid client by token:
+ 95c3afd44c5d87301dc3034b20b3fc75"}
+
+
[authz]模块用于管理client_details, user,以及获取access_token
去访问 [resources] 模块的资源.
登录系统,使用初始的账号 test/test 或去 Users 先创建用户, 这用于测试Shiro安全是否工作
+ +
+ 在开始OAuth2之前, 建议先理解OAuth2支持的5类grant_type
, 请访问 https://andaily.com/blog/?p=103,
+ 或直接去看看OAuth2协议 http://oauth.net/2/
+
+ 管理client_details, 在初始时创建了默认的管理client_details
+ test
+ 与
+ mobile
+ (见initial-db.ddl文件), 你可以去 client_details
+ 创建新的client_details来测试.
----- client_details是OAuth2中一个核心的组件
+
+ 查看 oauth_test.txt + 文件并进行OAuth2的流程测试; 也可下载 + spring-oauth-client + 项目来测试OAuth2的流程 +
++ Users -- 管理User +
++ client_details -- 管理client_details +
++ oauth_test.txt + -- 测试OAuth2的参考URL文件 +
++ API + -- oauth2-shiro提供的API文档 +
+
+ oauth_test.html --
+ 一个用于测试各类grant_type
的HTML页面
+
[authz]模块用于管理client_details, user,以及获取access_token
去访问 [resources] 模块的资源.
[authz]模块用于管理client_details, user,以及获取access_token
去访问 [resources] 模块的资源.
- 在开始OAuth2之前, 建议先理解OAuth2支持的5类grant_type
, 请访问 https://andaily.com/blog/?p=103,
- 或直接去看看OAuth2协议 http://oauth.net/2/
-
- 管理client_details, 在初始时创建了默认的管理client_details
- test
- 与
- mobile
- (见initial-db.ddl文件), 你可以去 client_details
- 创建新的client_details来测试.
----- client_details是OAuth2中一个核心的组件
-
- 查看 oauth_test.txt - 文件并进行OAuth2的流程测试; 也可下载 - spring-oauth-client - 项目来测试OAuth2的流程 -
-+ Users -- 管理User +
++ client_details -- 管理client_details +
++ oauth_test.txt + -- 测试OAuth2的参考URL文件 +
++ API + -- oauth2-shiro提供的API文档 +
+
+ oauth_test.html --
+ 一个用于测试各类grant_type
的HTML页面
+
- Users -- 管理User -
-- client_details -- 管理client_details -
-- oauth_test.txt - -- 测试OAuth2的参考URL文件 -
-- API - -- oauth2-shiro提供的API文档 -
-
- oauth_test.html --
- 一个用于测试各类grant_type
的HTML页面
-
+ oauth_test +
+根据不同的Role会显示不同的菜单 (Shiro权限控制)
+Username, unique.
+Password, required.
+Select Roles
+Username | +Roles[permission] | +CreateTime | +
---|---|---|
[[${user.username}]] | ++ + [[${r.roleName}]] [[${r.permissions}]] , + + | +[[${user.createTime}]] | +
Empty result
+
+ 每一个item对应oauth_client_details
表中的一条数据; 共[[${listDto.size}]]条数据.
+
+ 这里列出了一个 client_details 需要的所有属性进行添加, 但在实际使用场景中, 许多属性是由系统处理的, 不需要用户关心. +
+ +client_id必须输入,且必须唯一,长度至少5位; 在实际应用中的另一个名称叫appKey,与client_id是同一个概念.
+client_secret必须输入,且长度至少8位; + 在实际应用中的另一个名称叫appSecret,与client_secret是同一个概念.
+resourceIds, 用于定义一组资源的Id, 在[resources]模块中使用, + 可在[resources]模块的rs-security.xml查看定义的resourceId(每一个 OAuth2Filter 代表一个资源)
+scope必须选择
+至少勾选一项grant_type(s), 且不能只单独勾选refresh_token
, 若需更多帮助请访问 https://andaily.com/blog/?p=103
若grant_type
包括authorization_code,implicit,
+ 则必须输入redirect_uri
指定客户端所拥有的Shiro Role,可选; 尚未使用
+设定客户端的access_token的有效时间值(单位:秒),可选, 若不设定值则使用默认的有效时间值(60 * 60 * 12, 12小时); + 若设定则必须是大于0的整数值
+设定客户端的refresh_token的有效时间值(单位:秒),可选, 若不设定值则使用默认的有效时间值(60 * 60 * 24 * 30, + 30天); + 若设定则必须是大于0的整数值
+给Client起一个名称
+该Client的URI, 可选
+该Client的Icon URI, 可选
+Client的描述, 可选
+该属性是扩展的,
+ 只适用于grant_type(s)包括authorization_code
的情况,当用户登录成功后,若选No,则会跳转到让用户Approve的页面让用户同意授权,
+ 若选Yes,则在登录后不需要再让用户Approve同意授权(因为是受信任的)
Do you authorize '' to access your protected resources?
+ ++ 登录使用的 client_id: ''. +
+ +可以使用下面的初始账号登录或使用你自行添加的账号:
+username | +password | +grant_types | +roles | +
---|---|---|---|
test | +test | +authorization_code,password,refresh_token,client_credentials | +User(id=22) | +
+ 针对不同的grant_type
提供不同的测试URL,
+ 完整的OAuth测试请访问spring-oauth-client项目.
+
输入每一步必要的信息后点击其下面的链接地址.
+从 oauth-shiro 获取 'code'
+ 用 'code' 换取 'access_token'
+ 输入username, password 后点击链接地址.
+ username: +注意:password模式在OAuth2.1中已不推荐使用(安全系数差)
+输入redirect_uri 后点击链接地址. 获取access_token后注意查看redirect_uri的hash部分(#号后边部分)
+ redirect_uri: + +点击链接地址即可测试
+ + +输入refresh_token 后点击链接地址.
+ refresh_token: + +