mirror of
https://gitee.com/dromara/sa-token.git
synced 2025-12-21 10:59:45 +08:00
新增OAuth2.0接口
This commit is contained in:
@@ -30,6 +30,7 @@
|
||||
<div>当前Openid: <span class="openid"></span></div>
|
||||
<div>当前Access-Token: <span class="access_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>
|
||||
<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>
|
||||
|
||||
<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>
|
||||
|
||||
<br>
|
||||
@@ -202,7 +203,11 @@
|
||||
data: {accessToken: accessToken},
|
||||
dataType: 'json',
|
||||
success: function(res) {
|
||||
layer.alert(JSON.stringify(res.data));
|
||||
if(res.code == 200) {
|
||||
layer.alert(JSON.stringify(res.data));
|
||||
} else {
|
||||
layer.alert(res.msg);
|
||||
}
|
||||
},
|
||||
error: function(xhr, type, errorThrown){
|
||||
return layer.alert("异常:" + JSON.stringify(xhr));
|
||||
|
||||
@@ -76,6 +76,9 @@ public class SaOAuth2ServerController {
|
||||
Object loginId = SaOAuth2Util.getLoginIdByAccessToken(accessToken);
|
||||
System.out.println("-------- 此Access-Token对应的账号id: " + loginId);
|
||||
|
||||
// 校验 Access-Token 是否具有权限: userinfo
|
||||
SaOAuth2Util.checkScope(accessToken, "userinfo");
|
||||
|
||||
// 模拟账号信息 (真实环境需要查询数据库获取信息)
|
||||
Map<String, Object> map = new LinkedHashMap<String, Object>();
|
||||
map.put("nickname", "shengzhang_");
|
||||
|
||||
@@ -105,7 +105,35 @@ http://sa-oauth-server.com:8001/oauth2/refresh
|
||||
接口返回值同章节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
|
||||
|
||||
@@ -15,6 +15,7 @@ public class SaOAuth2Consts {
|
||||
public static String authorize = "/oauth2/authorize";
|
||||
public static String token = "/oauth2/token";
|
||||
public static String refresh = "/oauth2/refresh";
|
||||
public static String revoke = "/oauth2/revoke";
|
||||
public static String client_token = "/oauth2/client_token";
|
||||
public static String doLogin = "/oauth2/doLogin";
|
||||
public static String doConfirm = "/oauth2/doConfirm";
|
||||
@@ -33,6 +34,7 @@ public class SaOAuth2Consts {
|
||||
public static String state = "state";
|
||||
public static String code = "code";
|
||||
public static String token = "token";
|
||||
public static String access_token = "access_token";
|
||||
public static String refresh_token = "refresh_token";
|
||||
public static String grant_type = "grant_type";
|
||||
public static String username = "username";
|
||||
|
||||
@@ -51,6 +51,11 @@ public class SaOAuth2Handle {
|
||||
if(req.isPath(Api.refresh) && req.isParam(Param.grant_type, GrantType.refresh_token)) {
|
||||
return refreshToken(req);
|
||||
}
|
||||
|
||||
// 回收 Access-Token
|
||||
if(req.isPath(Api.revoke)) {
|
||||
return revokeToken(req);
|
||||
}
|
||||
|
||||
// doLogin 登录接口
|
||||
if(req.isPath(Api.doLogin)) {
|
||||
@@ -167,10 +172,34 @@ public class SaOAuth2Handle {
|
||||
SaOAuth2Util.checkRefreshTokenParam(clientId, clientSecret, refreshToken);
|
||||
|
||||
// 获取新Token返回
|
||||
Object data = SaOAuth2Util.saOAuth2Template.refreshAccessToken(refreshToken).toLineMap();
|
||||
Object data = SaOAuth2Util.refreshAccessToken(refreshToken).toLineMap();
|
||||
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 登录接口
|
||||
* @param req 请求对象
|
||||
|
||||
@@ -41,7 +41,7 @@ public class SaOAuth2Template {
|
||||
return null;
|
||||
}
|
||||
|
||||
// ------------------- 资源获取
|
||||
// ------------------- 资源校验API
|
||||
/**
|
||||
* 根据id获取Client信息, 如果Client为空,则抛出异常
|
||||
* @param clientId 应用id
|
||||
@@ -54,14 +54,6 @@ public class SaOAuth2Template {
|
||||
}
|
||||
return clientModel;
|
||||
}
|
||||
/**
|
||||
* 获取 access_token 所代表的LoginId
|
||||
* @param accessToken access_token
|
||||
* @return LoginId
|
||||
*/
|
||||
public Object getLoginIdByAccessToken(String accessToken) {
|
||||
return checkAccessToken(accessToken).loginId;
|
||||
}
|
||||
/**
|
||||
* 获取 Access-Token,如果AccessToken为空则抛出异常
|
||||
* @param accessToken .
|
||||
@@ -82,6 +74,29 @@ public class SaOAuth2Template {
|
||||
SaOAuth2Exception.throwBy(ct == null, "无效:client_token" + 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 构建数据
|
||||
/**
|
||||
@@ -277,7 +292,28 @@ public class SaOAuth2Template {
|
||||
}
|
||||
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 数据校验
|
||||
/**
|
||||
* 判断:指定 loginId 是否对一个 Client 授权给了指定 Scope
|
||||
@@ -389,6 +425,19 @@ public class SaOAuth2Template {
|
||||
// 返回Refresh-Token
|
||||
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 数据转换
|
||||
/**
|
||||
|
||||
@@ -21,7 +21,7 @@ public class SaOAuth2Util {
|
||||
public static SaOAuth2Template saOAuth2Template = new SaOAuth2Template();
|
||||
|
||||
|
||||
// ------------------- 资源获取
|
||||
// ------------------- 资源校验API
|
||||
|
||||
/**
|
||||
* 根据id获取Client信息, 如果Client为空,则抛出异常
|
||||
@@ -32,15 +32,6 @@ public class SaOAuth2Util {
|
||||
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为空则抛出异常
|
||||
* @param accessToken .
|
||||
@@ -58,7 +49,24 @@ public class SaOAuth2Util {
|
||||
public static ClientTokenModel checkClientToken(String 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 构建数据
|
||||
|
||||
@@ -141,6 +149,13 @@ public class SaOAuth2Util {
|
||||
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) {
|
||||
saOAuth2Template.checkRightUrl(clientId, url);
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验:clientId 与 clientSecret 是否正确
|
||||
* @param clientId 应用id
|
||||
@@ -205,6 +221,16 @@ public class SaOAuth2Util {
|
||||
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 数据
|
||||
|
||||
|
||||
Reference in New Issue
Block a user