@@ -18,7 +18,7 @@ import cn.dev33.satoken.stp.StpUtil;
import cn.dev33.satoken.util.SaResult ;
/**
* Sa-Token-OAuth2 请求处理类封装
* Sa-Token-OAuth2 请求处理类封装
* @author kong
*
*/
@@ -26,195 +26,195 @@ public class SaOAuth2Handle {
/**
* 处理Server端请求, 路由分发
* @return 处理结果
* @return 处理结果
*/
public static Object serverRequest ( ) {
// 获取变量
// 获取变量
SaRequest req = SaHolder . getRequest ( ) ;
SaResponse res = SaHolder . getResponse ( ) ;
SaOAuth2Config cfg = SaOAuth2Manager . getConfig ( ) ;
// ------------------ 路由分发 ------------------
// ------------------ 路由分发 ------------------
// 模式一: Code授权码
if ( req . isPath ( Api . authorize ) & & req . isParam ( Param . response_type , ResponseType . code ) & & cfg . isCode ) {
return authorize ( req , res , cfg ) ;
}
// Code授权码 获取 Access-Token
// Code授权码 获取 Access-Token
if ( req . isPath ( Api . token ) & & req . isParam ( Param . grant_type , GrantType . authorization_code ) ) {
return token ( req , res , cfg ) ;
}
// Refresh-Token 刷新 Access-Token
// Refresh-Token 刷新 Access-Token
if ( req . isPath ( Api . refresh ) & & req . isParam ( Param . grant_type , GrantType . refresh_token ) ) {
return refreshToken ( req ) ;
}
// 回收 Access-Token
// 回收 Access-Token
if ( req . isPath ( Api . revoke ) ) {
return revokeToken ( req ) ;
}
// doLogin 登录接口
// doLogin 登录接口
if ( req . isPath ( Api . doLogin ) ) {
return doLogin ( req , res , cfg ) ;
}
// doConfirm 确认授权接口
// doConfirm 确认授权接口
if ( req . isPath ( Api . doConfirm ) ) {
return doConfirm ( req ) ;
}
// 模式二:隐藏式
// 模式二:隐藏式
if ( req . isPath ( Api . authorize ) & & req . isParam ( Param . response_type , ResponseType . token ) & & cfg . isImplicit ) {
return authorize ( req , res , cfg ) ;
}
// 模式三:密码式
// 模式三:密码式
if ( req . isPath ( Api . token ) & & req . isParam ( Param . grant_type , GrantType . password ) & & cfg . isPassword ) {
return password ( req , res , cfg ) ;
}
// 模式四:凭证式
// 模式四:凭证式
if ( req . isPath ( Api . client_token ) & & req . isParam ( Param . grant_type , GrantType . client_credentials ) & & cfg . isClient ) {
return clientToken ( req , res , cfg ) ;
}
// 默认返回
// 默认返回
return SaOAuth2Consts . NOT_HANDLE ;
}
/**
* 模式一: Code授权码 / 模式二:隐藏式
* @param req 请求对象
* @param res 响应对象
* @param cfg 配置对象
* @return 处理结果
*/
public static Object authorize ( SaRequest req , SaResponse res , SaOAuth2Config cfg ) {
// 1、如果尚未登录, 则先去登录
/**
* 模式一: Code授权码 / 模式二:隐藏式
* @param req 请求对象
* @param res 响应对象
* @param cfg 配置对象
* @return 处理结果
*/
public static Object authorize ( SaRequest req , SaResponse res , SaOAuth2Config cfg ) {
// 1、如果尚未登录, 则先去登录
if ( StpUtil . isLogin ( ) = = false ) {
return cfg . notLoginView . get ( ) ;
}
// 2、构建请求Model
// 2、构建请求Model
RequestAuthModel ra = SaOAuth2Util . generateRequestAuth ( req , StpUtil . getLoginId ( ) ) ;
// 3、校验: 重定向域名是否合法
// 3、校验: 重定向域名是否合法
SaOAuth2Util . checkRightUrl ( ra . clientId , ra . redirectUri ) ;
// 4、校验: 此次申请的Scope, 该Client是否已经签约
// 4、校验: 此次申请的Scope, 该Client是否已经签约
SaOAuth2Util . checkContract ( ra . clientId , ra . scope ) ;
// 5、判断: 如果此次申请的Scope, 该用户尚未授权, 则转到授权页面
// 5、判断: 如果此次申请的Scope, 该用户尚未授权, 则转到授权页面
boolean isGrant = SaOAuth2Util . isGrant ( ra . loginId , ra . clientId , ra . scope ) ;
if ( isGrant = = false ) {
return cfg . confirmView . apply ( ra . clientId , ra . scope ) ;
}
// 6、判断授权类型
// 如果是 授权码式, 则: 开始重定向授权, 下放code
// 6、判断授权类型
// 如果是 授权码式, 则: 开始重定向授权, 下放code
if ( ResponseType . code . equals ( ra . responseType ) ) {
CodeModel codeModel = SaOAuth2Util . generateCode ( ra ) ;
CodeModel codeModel = SaOAuth2Util . generateCode ( ra ) ;
String redirectUri = SaOAuth2Util . buildRedirectUri ( ra . redirectUri , codeModel . code , ra . state ) ;
return res . redirect ( redirectUri ) ;
return res . redirect ( redirectUri ) ;
}
// 如果是 隐藏式,则:开始重定向授权,下放 token
// 如果是 隐藏式,则:开始重定向授权,下放 token
if ( ResponseType . token . equals ( ra . responseType ) ) {
AccessTokenModel at = SaOAuth2Util . generateAccessToken ( ra , false ) ;
AccessTokenModel at = SaOAuth2Util . generateAccessToken ( ra , false ) ;
String redirectUri = SaOAuth2Util . buildImplicitRedirectUri ( ra . redirectUri , at . accessToken , ra . state ) ;
return res . redirect ( redirectUri ) ;
return res . redirect ( redirectUri ) ;
}
// 默认返回
throw new SaOAuth2Exception ( " 无效response_type: " + ra . responseType ) ;
// 默认返回
throw new SaOAuth2Exception ( " 无效response_type: " + ra . responseType ) ;
}
/**
* Code授权码 获取 Access-Token
* @param req 请求对象
* @param res 响应对象
* @param cfg 配置对象
* @return 处理结果
* Code授权码 获取 Access-Token
* @param req 请求对象
* @param res 响应对象
* @param cfg 配置对象
* @return 处理结果
*/
public static Object token ( SaRequest req , SaResponse res , SaOAuth2Config cfg ) {
// 获取参数
String code = req . getParamNotNull ( Param . code ) ;
String clientId = req . getParamNotNull ( Param . client_id ) ;
// 获取参数
String code = req . getParamNotNull ( Param . code ) ;
String clientId = req . getParamNotNull ( Param . client_id ) ;
String clientSecret = req . getParamNotNull ( Param . client_secret ) ;
String redirectUri = req . getParam ( Param . redirect_uri ) ;
String redirectUri = req . getParam ( Param . redirect_uri ) ;
// 校验参数
SaOAuth2Util . checkGainTokenParam ( code , clientId , clientSecret , redirectUri ) ;
// 构建 Access-Token
// 构建 Access-Token
AccessTokenModel token = SaOAuth2Util . generateAccessToken ( code ) ;
// 返回
return SaResult . data ( token . toLineMap ( ) ) ;
// 返回
return SaResult . data ( token . toLineMap ( ) ) ;
}
/**
* Refresh-Token 刷新 Access-Token
* @param req 请求对象
* @return 处理结果
* Refresh-Token 刷新 Access-Token
* @param req 请求对象
* @return 处理结果
*/
public static Object refreshToken ( SaRequest req ) {
// 获取参数
// 获取参数
String clientId = req . getParamNotNull ( Param . client_id ) ;
String clientSecret = req . getParamNotNull ( Param . client_secret ) ;
String refreshToken = req . getParamNotNull ( Param . refresh_token ) ;
// 校验参数
// 校验参数
SaOAuth2Util . checkRefreshTokenParam ( clientId , clientSecret , refreshToken ) ;
// 获取新Token返回
// 获取新Token返回
Object data = SaOAuth2Util . refreshAccessToken ( refreshToken ) . toLineMap ( ) ;
return SaResult . data ( data ) ;
return SaResult . data ( data ) ;
}
/**
* 回收 Access-Token
* @param req 请求对象
* @return 处理结果
* 回收 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返回
// 获取新Token返回
SaOAuth2Util . revokeAccessToken ( accessToken ) ;
return SaResult . ok ( ) ;
return SaResult . ok ( ) ;
}
/**
* doLogin 登录接口
* @param req 请求对象
* @param res 响应对象
* @param cfg 配置对象
* @return 处理结果
* doLogin 登录接口
* @param req 请求对象
* @param res 响应对象
* @param cfg 配置对象
* @return 处理结果
*/
public static Object doLogin ( SaRequest req , SaResponse res , SaOAuth2Config cfg ) {
return cfg . doLoginHandle . apply ( req . getParamNotNull ( Param . name ) , req . getParamNotNull ( " pwd " ) ) ;
}
/**
* doConfirm 确认授权接口
* @param req 请求对象
* @return 处理结果
* doConfirm 确认授权接口
* @param req 请求对象
* @return 处理结果
*/
public static Object doConfirm ( SaRequest req ) {
String clientId = req . getParamNotNull ( Param . client_id ) ;
@@ -223,68 +223,71 @@ public class SaOAuth2Handle {
SaOAuth2Util . saveGrantScope ( clientId , loginId , scope ) ;
return SaResult . ok ( ) ;
}
/**
* 模式三:密码式
* @param req 请求对象
* @param res 响应对象
* @param cfg 配置对象
* @return 处理结果
* 模式三:密码式
* @param req 请求对象
* @param res 响应对象
* @param cfg 配置对象
* @return 处理结果
*/
public static Object password ( SaRequest req , SaResponse res , SaOAuth2Config cfg ) {
// 1、获取请求参数
// 1、获取请求参数
String username = req . getParamNotNull ( Param . username ) ;
String password = req . getParamNotNull ( Param . password ) ;
String clientId = req . getParamNotNull ( Param . client_id ) ;
// 2、校验client_id
SaOAuth2Util . checkClientModel ( clientId ) ;
// 3、防止因前端误传token造成逻辑干扰
// 3、防止因前端误传token造成逻辑干扰
SaHolder . getStorage ( ) . set ( StpUtil . stpLogic . splicingKeyJustCreatedSave ( ) , " no-token " ) ;
// 4、调用API 开始登录,如果没能成功登录,则直接退出
Object retObj = cfg . doLoginHandle . apply ( username , password ) ;
Object retObj = cfg . doLoginHandle . apply ( username , password ) ;
if ( StpUtil . isLogin ( ) = = false ) {
return retObj ;
}
// 5、构建 ra对象
// 5、构建 ra对象
RequestAuthModel ra = new RequestAuthModel ( ) ;
ra . clientId = clientId ;
ra . loginId = StpUtil . getLoginId ( ) ;
ra . scope = req . getParam ( Param . scope , " " ) ;
// 6、生成 Access-Token
AccessTokenModel at = SaOAuth2Util . generateAccessToken ( ra , true ) ;
// 7、返回 Access-Token
ra . loginId = StpUtil . getLoginId ( ) ;
ra . scope = req . getParam ( Param . scope , " " ) ;
// 6、生成 Access-Token
AccessTokenModel at = SaOAuth2Util . generateAccessToken ( ra , true ) ;
// 7、返回 Access-Token
return SaResult . data ( at . toLineMap ( ) ) ;
}
/**
* 模式四:凭证式
* @param req 请求对象
* @param res 响应对象
* @param cfg 配置对象
* @return 处理结果
* 模式四:凭证式
* @param req 请求对象
* @param res 响应对象
* @param cfg 配置对象
* @return 处理结果
*/
public static Object clientToken ( SaRequest req , SaResponse res , SaOAuth2Config cfg ) {
// 获取参数
// 获取参数
String clientId = req . getParamNotNull ( Param . client_id ) ;
String clientSecret = req . getParamNotNull ( Param . client_secret ) ;
String scope = req . getParam ( Param . scope ) ;
//校验 ClientScope
SaOAuth2Util . checkContract ( clientId , scope ) ;
// 校验 ClientSecret
SaOAuth2Util . checkClientSecret ( clientId , clientSecret ) ;
// 返回 Client-Token
ClientTokenModel ct = SaOAuth2Util . generateClientToken ( clientId , scope ) ;
// 返回 Client-Token
return SaResult . data ( ct . toLineMap ( ) ) ;
return SaResult . data ( ct . toLineMap ( ) ) ;
}
}