mirror of
https://gitee.com/dromara/sa-token.git
synced 2025-12-21 19:09:45 +08:00
新增OAuth2.0接口
This commit is contained in:
@@ -30,6 +30,7 @@
|
|||||||
<div>当前Openid: <span class="openid"></span></div>
|
<div>当前Openid: <span class="openid"></span></div>
|
||||||
<div>当前Access-Token: <span class="access_token"></span></div>
|
<div>当前Access-Token: <span class="access_token"></span></div>
|
||||||
<div>当前Refresh-Token: <span class="refresh_token"></span></div>
|
<div>当前Refresh-Token: <span class="refresh_token"></span></div>
|
||||||
|
<div>当前令牌包含Scope: <span class="scope"></span></div>
|
||||||
<div>当前Client-Token: <span class="client_token"></span></div>
|
<div>当前Client-Token: <span class="client_token"></span></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="btn-box">
|
<div class="btn-box">
|
||||||
@@ -58,7 +59,7 @@
|
|||||||
<code>http://sa-oauth-server.com:8001/oauth2/refresh?grant_type=refresh_token&client_id={value}&client_secret={value}&refresh_token={value}</code>
|
<code>http://sa-oauth-server.com:8001/oauth2/refresh?grant_type=refresh_token&client_id={value}&client_secret={value}&refresh_token={value}</code>
|
||||||
|
|
||||||
<button onclick="getUserinfo()">获取账号信息</button>
|
<button onclick="getUserinfo()">获取账号信息</button>
|
||||||
<span class="ps">使用 Access-Token 置换资源: 获取账号昵称、头像、性别等信息 </span>
|
<span class="ps">使用 Access-Token 置换资源: 获取账号昵称、头像、性别等信息 (Access-Token具备userinfo权限时才可以获取成功) </span>
|
||||||
<code>http://sa-oauth-server.com:8001/oauth2/userinfo?access_token={value}</code>
|
<code>http://sa-oauth-server.com:8001/oauth2/userinfo?access_token={value}</code>
|
||||||
|
|
||||||
<br>
|
<br>
|
||||||
@@ -202,7 +203,11 @@
|
|||||||
data: {accessToken: accessToken},
|
data: {accessToken: accessToken},
|
||||||
dataType: 'json',
|
dataType: 'json',
|
||||||
success: function(res) {
|
success: function(res) {
|
||||||
|
if(res.code == 200) {
|
||||||
layer.alert(JSON.stringify(res.data));
|
layer.alert(JSON.stringify(res.data));
|
||||||
|
} else {
|
||||||
|
layer.alert(res.msg);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
error: function(xhr, type, errorThrown){
|
error: function(xhr, type, errorThrown){
|
||||||
return layer.alert("异常:" + JSON.stringify(xhr));
|
return layer.alert("异常:" + JSON.stringify(xhr));
|
||||||
|
|||||||
@@ -76,6 +76,9 @@ public class SaOAuth2ServerController {
|
|||||||
Object loginId = SaOAuth2Util.getLoginIdByAccessToken(accessToken);
|
Object loginId = SaOAuth2Util.getLoginIdByAccessToken(accessToken);
|
||||||
System.out.println("-------- 此Access-Token对应的账号id: " + loginId);
|
System.out.println("-------- 此Access-Token对应的账号id: " + loginId);
|
||||||
|
|
||||||
|
// 校验 Access-Token 是否具有权限: userinfo
|
||||||
|
SaOAuth2Util.checkScope(accessToken, "userinfo");
|
||||||
|
|
||||||
// 模拟账号信息 (真实环境需要查询数据库获取信息)
|
// 模拟账号信息 (真实环境需要查询数据库获取信息)
|
||||||
Map<String, Object> map = new LinkedHashMap<String, Object>();
|
Map<String, Object> map = new LinkedHashMap<String, Object>();
|
||||||
map.put("nickname", "shengzhang_");
|
map.put("nickname", "shengzhang_");
|
||||||
|
|||||||
@@ -105,7 +105,35 @@ http://sa-oauth-server.com:8001/oauth2/refresh
|
|||||||
接口返回值同章节1.2,此处不再赘述
|
接口返回值同章节1.2,此处不再赘述
|
||||||
|
|
||||||
|
|
||||||
### 1.4、根据 Access-Token 获取相应用户的账号信息
|
### 1.4、回收 Access-Token (如果需要的话)
|
||||||
|
在Access-Token过期前主动将其回收
|
||||||
|
|
||||||
|
``` url
|
||||||
|
http://sa-oauth-server.com:8001/oauth2/revoke
|
||||||
|
?client_id={value}
|
||||||
|
&client_secret={value}
|
||||||
|
&access_token={value}
|
||||||
|
```
|
||||||
|
|
||||||
|
参数详解:
|
||||||
|
|
||||||
|
| 参数 | 是否必填 | 说明 |
|
||||||
|
| :-------- | :-------- | :-------- |
|
||||||
|
| client_id | 是 | 应用id |
|
||||||
|
| client_secret | 是 | 应用秘钥 |
|
||||||
|
| access_token | 是 | 步骤1.2中获取到的`Access-Token`值 |
|
||||||
|
|
||||||
|
返回值样例:
|
||||||
|
``` js
|
||||||
|
{
|
||||||
|
"code": 200,
|
||||||
|
"msg": "ok",
|
||||||
|
"data": null
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
### 1.5、根据 Access-Token 获取相应用户的账号信息
|
||||||
注:此接口为官方仓库模拟接口,正式项目中大家可以根据此样例,自定义需要的接口及参数
|
注:此接口为官方仓库模拟接口,正式项目中大家可以根据此样例,自定义需要的接口及参数
|
||||||
|
|
||||||
``` url
|
``` url
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ public class SaOAuth2Consts {
|
|||||||
public static String authorize = "/oauth2/authorize";
|
public static String authorize = "/oauth2/authorize";
|
||||||
public static String token = "/oauth2/token";
|
public static String token = "/oauth2/token";
|
||||||
public static String refresh = "/oauth2/refresh";
|
public static String refresh = "/oauth2/refresh";
|
||||||
|
public static String revoke = "/oauth2/revoke";
|
||||||
public static String client_token = "/oauth2/client_token";
|
public static String client_token = "/oauth2/client_token";
|
||||||
public static String doLogin = "/oauth2/doLogin";
|
public static String doLogin = "/oauth2/doLogin";
|
||||||
public static String doConfirm = "/oauth2/doConfirm";
|
public static String doConfirm = "/oauth2/doConfirm";
|
||||||
@@ -33,6 +34,7 @@ public class SaOAuth2Consts {
|
|||||||
public static String state = "state";
|
public static String state = "state";
|
||||||
public static String code = "code";
|
public static String code = "code";
|
||||||
public static String token = "token";
|
public static String token = "token";
|
||||||
|
public static String access_token = "access_token";
|
||||||
public static String refresh_token = "refresh_token";
|
public static String refresh_token = "refresh_token";
|
||||||
public static String grant_type = "grant_type";
|
public static String grant_type = "grant_type";
|
||||||
public static String username = "username";
|
public static String username = "username";
|
||||||
|
|||||||
@@ -52,6 +52,11 @@ public class SaOAuth2Handle {
|
|||||||
return refreshToken(req);
|
return refreshToken(req);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 回收 Access-Token
|
||||||
|
if(req.isPath(Api.revoke)) {
|
||||||
|
return revokeToken(req);
|
||||||
|
}
|
||||||
|
|
||||||
// doLogin 登录接口
|
// doLogin 登录接口
|
||||||
if(req.isPath(Api.doLogin)) {
|
if(req.isPath(Api.doLogin)) {
|
||||||
return doLogin(req, res, cfg);
|
return doLogin(req, res, cfg);
|
||||||
@@ -167,10 +172,34 @@ public class SaOAuth2Handle {
|
|||||||
SaOAuth2Util.checkRefreshTokenParam(clientId, clientSecret, refreshToken);
|
SaOAuth2Util.checkRefreshTokenParam(clientId, clientSecret, refreshToken);
|
||||||
|
|
||||||
// 获取新Token返回
|
// 获取新Token返回
|
||||||
Object data = SaOAuth2Util.saOAuth2Template.refreshAccessToken(refreshToken).toLineMap();
|
Object data = SaOAuth2Util.refreshAccessToken(refreshToken).toLineMap();
|
||||||
return SaResult.data(data);
|
return SaResult.data(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 回收 Access-Token
|
||||||
|
* @param req 请求对象
|
||||||
|
* @return 处理结果
|
||||||
|
*/
|
||||||
|
public static Object revokeToken(SaRequest req) {
|
||||||
|
// 获取参数
|
||||||
|
String clientId = req.getParamNotNull(Param.client_id);
|
||||||
|
String clientSecret = req.getParamNotNull(Param.client_secret);
|
||||||
|
String accessToken = req.getParamNotNull(Param.access_token);
|
||||||
|
|
||||||
|
// 如果 Access-Token 不存在,直接返回
|
||||||
|
if(SaOAuth2Util.getAccessToken(accessToken) == null) {
|
||||||
|
return SaResult.ok("access_token不存在:" + accessToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 校验参数
|
||||||
|
SaOAuth2Util.checkAccessTokenParam(clientId, clientSecret, accessToken);
|
||||||
|
|
||||||
|
// 获取新Token返回
|
||||||
|
SaOAuth2Util.revokeAccessToken(accessToken);
|
||||||
|
return SaResult.ok();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* doLogin 登录接口
|
* doLogin 登录接口
|
||||||
* @param req 请求对象
|
* @param req 请求对象
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ public class SaOAuth2Template {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------- 资源获取
|
// ------------------- 资源校验API
|
||||||
/**
|
/**
|
||||||
* 根据id获取Client信息, 如果Client为空,则抛出异常
|
* 根据id获取Client信息, 如果Client为空,则抛出异常
|
||||||
* @param clientId 应用id
|
* @param clientId 应用id
|
||||||
@@ -54,14 +54,6 @@ public class SaOAuth2Template {
|
|||||||
}
|
}
|
||||||
return clientModel;
|
return clientModel;
|
||||||
}
|
}
|
||||||
/**
|
|
||||||
* 获取 access_token 所代表的LoginId
|
|
||||||
* @param accessToken access_token
|
|
||||||
* @return LoginId
|
|
||||||
*/
|
|
||||||
public Object getLoginIdByAccessToken(String accessToken) {
|
|
||||||
return checkAccessToken(accessToken).loginId;
|
|
||||||
}
|
|
||||||
/**
|
/**
|
||||||
* 获取 Access-Token,如果AccessToken为空则抛出异常
|
* 获取 Access-Token,如果AccessToken为空则抛出异常
|
||||||
* @param accessToken .
|
* @param accessToken .
|
||||||
@@ -82,6 +74,29 @@ public class SaOAuth2Template {
|
|||||||
SaOAuth2Exception.throwBy(ct == null, "无效:client_token" + ct);
|
SaOAuth2Exception.throwBy(ct == null, "无效:client_token" + ct);
|
||||||
return ct;
|
return ct;
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* 获取 Access-Token 所代表的LoginId
|
||||||
|
* @param accessToken Access-Token
|
||||||
|
* @return LoginId
|
||||||
|
*/
|
||||||
|
public Object getLoginIdByAccessToken(String accessToken) {
|
||||||
|
return checkAccessToken(accessToken).loginId;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 校验:指定 Access-Token 是否具有指定 Scope
|
||||||
|
* @param accessToken Access-Token
|
||||||
|
* @param scopes 需要校验的权限列表
|
||||||
|
*/
|
||||||
|
public void checkScope(String accessToken, String... scopes) {
|
||||||
|
if(scopes == null || scopes.length == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
AccessTokenModel at = checkAccessToken(accessToken);
|
||||||
|
List<String> scopeList = SaFoxUtil.convertStringToList(at.scope);
|
||||||
|
for (String scope : scopes) {
|
||||||
|
SaOAuth2Exception.throwBy(scopeList.contains(scope) == false, "该 Access-Token 不具备 Scope:" + scope);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ------------------- generate 构建数据
|
// ------------------- generate 构建数据
|
||||||
/**
|
/**
|
||||||
@@ -277,6 +292,27 @@ public class SaOAuth2Template {
|
|||||||
}
|
}
|
||||||
return url;
|
return url;
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* 回收 Access-Token
|
||||||
|
* @param accessToken Access-Token值
|
||||||
|
*/
|
||||||
|
public void revokeAccessToken(String accessToken) {
|
||||||
|
|
||||||
|
// 如果查不到任何东西, 直接返回
|
||||||
|
AccessTokenModel at = getAccessToken(accessToken);
|
||||||
|
if(at == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 删除 Access-Token
|
||||||
|
deleteAccessToken(accessToken);
|
||||||
|
deleteAccessTokenIndex(at.clientId, at.accessToken);
|
||||||
|
|
||||||
|
// 删除对应的 Refresh-Token
|
||||||
|
String refreshToken = getRefreshTokenValue(at.clientId, at.loginId);
|
||||||
|
deleteRefreshToken(refreshToken);
|
||||||
|
deleteRefreshTokenIndex(at.clientId, at.loginId);
|
||||||
|
}
|
||||||
|
|
||||||
// ------------------- check 数据校验
|
// ------------------- check 数据校验
|
||||||
/**
|
/**
|
||||||
@@ -389,6 +425,19 @@ public class SaOAuth2Template {
|
|||||||
// 返回Refresh-Token
|
// 返回Refresh-Token
|
||||||
return rt;
|
return rt;
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* 校验:Access-Token、clientId、clientSecret 三者是否匹配成功
|
||||||
|
* @param clientId 应用id
|
||||||
|
* @param clientSecret 秘钥
|
||||||
|
* @param accessToken Access-Token
|
||||||
|
* @return SaClientModel对象
|
||||||
|
*/
|
||||||
|
public AccessTokenModel checkAccessTokenParam(String clientId, String clientSecret, String accessToken) {
|
||||||
|
AccessTokenModel at = checkAccessToken(accessToken);
|
||||||
|
SaOAuth2Exception.throwBy(at.clientId.equals(clientId) == false, "无效client_id:" + clientId);
|
||||||
|
checkClientSecret(clientId, clientSecret);
|
||||||
|
return at;
|
||||||
|
}
|
||||||
|
|
||||||
// ------------------- conver 数据转换
|
// ------------------- conver 数据转换
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ public class SaOAuth2Util {
|
|||||||
public static SaOAuth2Template saOAuth2Template = new SaOAuth2Template();
|
public static SaOAuth2Template saOAuth2Template = new SaOAuth2Template();
|
||||||
|
|
||||||
|
|
||||||
// ------------------- 资源获取
|
// ------------------- 资源校验API
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 根据id获取Client信息, 如果Client为空,则抛出异常
|
* 根据id获取Client信息, 如果Client为空,则抛出异常
|
||||||
@@ -32,15 +32,6 @@ public class SaOAuth2Util {
|
|||||||
return saOAuth2Template.checkClientModel(clientId);
|
return saOAuth2Template.checkClientModel(clientId);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取 access_token 所代表的LoginId
|
|
||||||
* @param accessToken access_token
|
|
||||||
* @return LoginId
|
|
||||||
*/
|
|
||||||
public static Object getLoginIdByAccessToken(String accessToken) {
|
|
||||||
return saOAuth2Template.getLoginIdByAccessToken(accessToken);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取 Access-Token,如果AccessToken为空则抛出异常
|
* 获取 Access-Token,如果AccessToken为空则抛出异常
|
||||||
* @param accessToken .
|
* @param accessToken .
|
||||||
@@ -59,6 +50,23 @@ public class SaOAuth2Util {
|
|||||||
return saOAuth2Template.checkClientToken(clientToken);
|
return saOAuth2Template.checkClientToken(clientToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取 Access-Token 所代表的LoginId
|
||||||
|
* @param accessToken Access-Token
|
||||||
|
* @return LoginId
|
||||||
|
*/
|
||||||
|
public static Object getLoginIdByAccessToken(String accessToken) {
|
||||||
|
return saOAuth2Template.getLoginIdByAccessToken(accessToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 校验:指定 Access-Token 是否具有指定 Scope
|
||||||
|
* @param accessToken Access-Token
|
||||||
|
* @param scopes 需要校验的权限列表
|
||||||
|
*/
|
||||||
|
public static void checkScope(String accessToken, String... scopes) {
|
||||||
|
saOAuth2Template.checkScope(accessToken, scopes);
|
||||||
|
}
|
||||||
|
|
||||||
// ------------------- generate 构建数据
|
// ------------------- generate 构建数据
|
||||||
|
|
||||||
@@ -141,6 +149,13 @@ public class SaOAuth2Util {
|
|||||||
return saOAuth2Template.buildImplicitRedirectUri(redirectUri, token, state);
|
return saOAuth2Template.buildImplicitRedirectUri(redirectUri, token, state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 回收 Access-Token
|
||||||
|
* @param accessToken Access-Token值
|
||||||
|
*/
|
||||||
|
public static void revokeAccessToken(String accessToken) {
|
||||||
|
saOAuth2Template.revokeAccessToken(accessToken);
|
||||||
|
}
|
||||||
|
|
||||||
// ------------------- 数据校验
|
// ------------------- 数据校验
|
||||||
|
|
||||||
@@ -172,6 +187,7 @@ public class SaOAuth2Util {
|
|||||||
public static void checkRightUrl(String clientId, String url) {
|
public static void checkRightUrl(String clientId, String url) {
|
||||||
saOAuth2Template.checkRightUrl(clientId, url);
|
saOAuth2Template.checkRightUrl(clientId, url);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 校验:clientId 与 clientSecret 是否正确
|
* 校验:clientId 与 clientSecret 是否正确
|
||||||
* @param clientId 应用id
|
* @param clientId 应用id
|
||||||
@@ -205,6 +221,16 @@ public class SaOAuth2Util {
|
|||||||
return saOAuth2Template.checkRefreshTokenParam(clientId, clientSecret, refreshToken);
|
return saOAuth2Template.checkRefreshTokenParam(clientId, clientSecret, refreshToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 校验:Access-Token、clientId、clientSecret 三者是否匹配成功
|
||||||
|
* @param clientId 应用id
|
||||||
|
* @param clientSecret 秘钥
|
||||||
|
* @param accessToken Access-Token
|
||||||
|
* @return SaClientModel对象
|
||||||
|
*/
|
||||||
|
public static AccessTokenModel checkAccessTokenParam(String clientId, String clientSecret, String accessToken) {
|
||||||
|
return saOAuth2Template.checkAccessTokenParam(clientId, clientSecret, accessToken);
|
||||||
|
}
|
||||||
|
|
||||||
// ------------------- save 数据
|
// ------------------- save 数据
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user