mirror of
https://gitee.com/durcframework/SOP.git
synced 2025-08-11 21:57:56 +08:00
新增应用授权
This commit is contained in:
@@ -9,6 +9,7 @@
|
||||
<packaging>pom</packaging>
|
||||
|
||||
<modules>
|
||||
<module>sop-auth</module>
|
||||
<module>sop-story</module>
|
||||
<module>sop-book</module>
|
||||
<module>sop-easyopen</module>
|
||||
|
29
sop-example/sop-auth/.gitignore
vendored
Normal file
29
sop-example/sop-auth/.gitignore
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
HELP.md
|
||||
/target/
|
||||
!.mvn/wrapper/maven-wrapper.jar
|
||||
|
||||
### STS ###
|
||||
.apt_generated
|
||||
.classpath
|
||||
.factorypath
|
||||
.project
|
||||
.settings
|
||||
.springBeans
|
||||
.sts4-cache
|
||||
|
||||
### IntelliJ IDEA ###
|
||||
.idea
|
||||
*.iws
|
||||
*.iml
|
||||
*.ipr
|
||||
|
||||
### NetBeans ###
|
||||
/nbproject/private/
|
||||
/nbbuild/
|
||||
/dist/
|
||||
/nbdist/
|
||||
/.nb-gradle/
|
||||
/build/
|
||||
|
||||
### VS Code ###
|
||||
.vscode/
|
127
sop-example/sop-auth/pom.xml
Normal file
127
sop-example/sop-auth/pom.xml
Normal file
@@ -0,0 +1,127 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-parent</artifactId>
|
||||
<version>2.1.2.RELEASE</version>
|
||||
<relativePath/> <!-- lookup parent from repository -->
|
||||
</parent>
|
||||
<groupId>com.gitee.sop</groupId>
|
||||
<artifactId>sop-auth</artifactId>
|
||||
<version>1.0.0-SNAPSHOT</version>
|
||||
<name>sop-auth</name>
|
||||
<description>授权程序</description>
|
||||
|
||||
<properties>
|
||||
<java.version>1.8</java.version>
|
||||
<spring-cloud.version>Greenwich.RELEASE</spring-cloud.version>
|
||||
<oltu.version>0.31</oltu.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
|
||||
<!-- sop相关配置 -->
|
||||
<dependency>
|
||||
<groupId>com.gitee.sop</groupId>
|
||||
<artifactId>sop-service-common</artifactId>
|
||||
<version>1.6.0-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-openfeign</artifactId>
|
||||
</dependency>
|
||||
<!-- sop相关配置 end-->
|
||||
|
||||
<dependency>
|
||||
<groupId>com.gitee.sop</groupId>
|
||||
<artifactId>sdk-java</artifactId>
|
||||
<version>1.0.0-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.squareup.okhttp3</groupId>
|
||||
<artifactId>okhttp</artifactId>
|
||||
<version>3.14.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>net.oschina.durcframework</groupId>
|
||||
<artifactId>fastmybatis-spring-boot-starter</artifactId>
|
||||
<version>1.7.1</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>mysql</groupId>
|
||||
<artifactId>mysql-connector-java</artifactId>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- oauth2服务端 -->
|
||||
<dependency>
|
||||
<groupId>org.apache.oltu.oauth2</groupId>
|
||||
<artifactId>org.apache.oltu.oauth2.authzserver</artifactId>
|
||||
<version>${oltu.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.oltu.oauth2</groupId>
|
||||
<artifactId>org.apache.oltu.oauth2.resourceserver</artifactId>
|
||||
<version>${oltu.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-thymeleaf</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-data-redis</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.guava</groupId>
|
||||
<artifactId>guava</artifactId>
|
||||
<version>27.1-jre</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<dependencyManagement>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-dependencies</artifactId>
|
||||
<version>${spring-cloud.version}</version>
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
</project>
|
9
sop-example/sop-auth/readme.md
Normal file
9
sop-example/sop-auth/readme.md
Normal file
@@ -0,0 +1,9 @@
|
||||
# 应用授权
|
||||
|
||||
- 启动注册中心、网关、本服务(sop-auth)
|
||||
- 浏览器访问:http://localhost:8087/oauth2/appToAppAuth?app_id=2019032617262200001&redirect_uri=http%3a%2f%2flocalhost%3a8087%2foauth2callback
|
||||
- 输入用户名密码登录,这里是`zhangsan/123456`
|
||||
|
||||
授权接口在`OAuth2Controller`中,查看回调在`CallbackController`中
|
||||
|
||||
token的维护,重点关注`OAuth2ManagerRedis.java`
|
@@ -0,0 +1,15 @@
|
||||
package com.gitee.sop.sopauth;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
|
||||
|
||||
@EnableDiscoveryClient
|
||||
@SpringBootApplication
|
||||
public class SopAuthApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(SopAuthApplication.class, args);
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,44 @@
|
||||
package com.gitee.sop.sopauth.auth;
|
||||
|
||||
/**
|
||||
* @author tanghc
|
||||
*/
|
||||
public class AccessToken {
|
||||
/** 过期时间,毫秒 */
|
||||
private long expireTimeMillis;
|
||||
private OpenUser openUser;
|
||||
|
||||
/**
|
||||
* @param expireIn 有效时长,秒
|
||||
* @param openUser
|
||||
*/
|
||||
public AccessToken(long expireIn, OpenUser openUser) {
|
||||
super();
|
||||
if(expireIn <= 0) {
|
||||
throw new IllegalArgumentException("expireIn必须大于0");
|
||||
}
|
||||
this.expireTimeMillis = System.currentTimeMillis() + (expireIn * 1000);
|
||||
this.openUser = openUser;
|
||||
}
|
||||
|
||||
public boolean isExpired() {
|
||||
return expireTimeMillis < System.currentTimeMillis();
|
||||
}
|
||||
|
||||
public long getExpireTimeMillis() {
|
||||
return expireTimeMillis;
|
||||
}
|
||||
|
||||
public void setExpireTimeMillis(long expireTimeMillis) {
|
||||
this.expireTimeMillis = expireTimeMillis;
|
||||
}
|
||||
|
||||
public OpenUser getOpenUser() {
|
||||
return openUser;
|
||||
}
|
||||
|
||||
public void setOpenUser(OpenUser openUser) {
|
||||
this.openUser = openUser;
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,14 @@
|
||||
package com.gitee.sop.sopauth.auth;
|
||||
|
||||
/**
|
||||
* @author tanghc
|
||||
*/
|
||||
public interface AppIdManager {
|
||||
/**
|
||||
* 是否是合法的appId
|
||||
*
|
||||
* @param appId
|
||||
* @return true:合法
|
||||
*/
|
||||
boolean isValidAppId(String appId);
|
||||
}
|
@@ -0,0 +1,30 @@
|
||||
package com.gitee.sop.sopauth.auth;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
|
||||
/**
|
||||
* 获取accessToken参数对象
|
||||
* @author tanghc
|
||||
*/
|
||||
@Data
|
||||
public class FetchTokenParam {
|
||||
/**
|
||||
* 授权类型。<br>
|
||||
* 如果使用app_auth_code换取token,则为authorization_code,
|
||||
* 如果使用refresh_token换取新的token,则为refresh_token
|
||||
*/
|
||||
@NotBlank(message = "授权类型不能为空")
|
||||
private String grant_type;
|
||||
|
||||
/**
|
||||
* 授权码.与refresh_token二选一,用户对应用授权后得到,即第一步中开发者获取到的app_auth_code值
|
||||
*/
|
||||
private String code;
|
||||
|
||||
/**
|
||||
* 刷新令牌.与code二选一,可为空,刷新令牌时使用
|
||||
*/
|
||||
private String refresh_token;
|
||||
}
|
@@ -0,0 +1,39 @@
|
||||
package com.gitee.sop.sopauth.auth;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 使用app_auth_code换取app_auth_token返回结果
|
||||
* @author tanghc
|
||||
*/
|
||||
@Data
|
||||
public class FetchTokenResult {
|
||||
/**
|
||||
* 授权令牌
|
||||
*/
|
||||
private String app_auth_token;
|
||||
|
||||
/**
|
||||
* 用户id
|
||||
*/
|
||||
private String user_id;
|
||||
|
||||
/**
|
||||
* 令牌有效期. -1:永久有效
|
||||
*/
|
||||
private long expires_in = -1;
|
||||
|
||||
/**
|
||||
* 刷新令牌有效期. -1:永久有效
|
||||
*/
|
||||
private long re_expires_in = -1;
|
||||
|
||||
/**
|
||||
* 刷新令牌时使用。
|
||||
* 刷新令牌后,我们会保证老的app_auth_token从刷新开始10分钟内可继续使用,请及时替换为最新token
|
||||
*/
|
||||
private String app_refresh_token;
|
||||
|
||||
private String error;
|
||||
private String error_description;
|
||||
}
|
@@ -0,0 +1,46 @@
|
||||
package com.gitee.sop.sopauth.auth;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* @author tanghc
|
||||
*/
|
||||
@Data
|
||||
public class OAuth2Config {
|
||||
|
||||
private static OAuth2Config instance = new OAuth2Config();
|
||||
|
||||
public static OAuth2Config getInstance() {
|
||||
return instance;
|
||||
}
|
||||
|
||||
public static void setInstance(OAuth2Config instance) {
|
||||
OAuth2Config.instance = instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* 应用授权的app_auth_code唯一的;app_auth_code使用一次后失效,一天(从生成app_auth_code开始的24小时)未被使用自动过期;
|
||||
* app_auth_token永久有效。
|
||||
*/
|
||||
private int codeTimeoutSeconds = 86400;
|
||||
/**
|
||||
* accessToken有效时间,单位秒
|
||||
* -1 永久有效
|
||||
*/
|
||||
private int accessTokenExpiresIn = -1;
|
||||
|
||||
/**
|
||||
* app_refresh_token有效时间,单位秒,accessToken有效时间的3倍。当小于0,永久有效
|
||||
*/
|
||||
private int refreshTokenExpiresIn = accessTokenExpiresIn * 3;
|
||||
|
||||
/**
|
||||
* 刷新令牌后,我们会保证老的app_auth_token从刷新开始10分钟内可继续使用,请及时替换为最新token
|
||||
*/
|
||||
private int afterRefreshExpiresIn = 60 * 10;
|
||||
|
||||
/**
|
||||
* 登录视图页面用于,mvc视图,如:loginView
|
||||
*/
|
||||
private String oauth2LoginUri = "/oauth2/login";
|
||||
}
|
@@ -0,0 +1,93 @@
|
||||
package com.gitee.sop.sopauth.auth;
|
||||
|
||||
|
||||
import com.gitee.sop.sopauth.auth.exception.LoginErrorException;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 认证服务,需要自己实现
|
||||
* @author tanghc
|
||||
*
|
||||
*/
|
||||
public interface OAuth2Manager {
|
||||
|
||||
/**
|
||||
* 添加 auth code
|
||||
*
|
||||
* @param authCode
|
||||
* code值
|
||||
* @param authUser
|
||||
* 用户
|
||||
*/
|
||||
void addAuthCode(String authCode, OpenUser authUser);
|
||||
|
||||
/**
|
||||
* 添加accessToken
|
||||
* @param accessToken token值
|
||||
* @param refreshToken refreshToken
|
||||
* @param authUser 用户
|
||||
*/
|
||||
void addAccessToken(String accessToken, String refreshToken, OpenUser authUser);
|
||||
|
||||
|
||||
/**
|
||||
* 删除这个accessToken
|
||||
* @param accessToken
|
||||
*/
|
||||
void removeAccessToken(String accessToken);
|
||||
|
||||
/**
|
||||
* 删除这个refreshToken
|
||||
* @param refreshToken
|
||||
*/
|
||||
void removeRefreshToken(String refreshToken);
|
||||
|
||||
/**
|
||||
* 获取RefreshToken
|
||||
* @param refreshToken
|
||||
* @return 返回Token信息
|
||||
*/
|
||||
RefreshToken getRefreshToken(String refreshToken);
|
||||
|
||||
/**
|
||||
* 验证auth code是否有效
|
||||
*
|
||||
* @param authCode
|
||||
* @return 无效返回false
|
||||
*/
|
||||
boolean checkAuthCode(String authCode);
|
||||
|
||||
/**
|
||||
* 根据auth code获取用户
|
||||
*
|
||||
* @param authCode
|
||||
* @return 返回用户
|
||||
*/
|
||||
OpenUser getUserByAuthCode(String authCode);
|
||||
|
||||
/**
|
||||
* 根据access token获取用户名
|
||||
*
|
||||
* @param accessToken
|
||||
* token值
|
||||
* @return 返回用户
|
||||
*/
|
||||
OpenUser getUserByAccessToken(String accessToken);
|
||||
|
||||
/**
|
||||
* 返回accessToken中追加的参数
|
||||
* @param user
|
||||
* @return 返回追加的参数
|
||||
*/
|
||||
Map<String, String> getParam(OpenUser user);
|
||||
|
||||
/**
|
||||
* 用户登录,需判断是否已经登录
|
||||
* @param request
|
||||
* @return 返回用户对象
|
||||
* @throws LoginErrorException 登录失败异常
|
||||
*/
|
||||
OpenUser login(HttpServletRequest request) throws LoginErrorException;
|
||||
}
|
@@ -0,0 +1,44 @@
|
||||
package com.gitee.sop.sopauth.auth;
|
||||
|
||||
import org.apache.oltu.oauth2.common.exception.OAuthSystemException;
|
||||
import org.apache.oltu.oauth2.common.message.OAuthResponse;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.net.URISyntaxException;
|
||||
|
||||
/**
|
||||
* @author tanghc
|
||||
*/
|
||||
public interface OAuth2Service {
|
||||
|
||||
/**
|
||||
* oauth2授权,获取code.
|
||||
* <pre>
|
||||
* 1、首先通过如http://localhost:8080/api/authorize?client_id=test&response_type=code&redirect_uri=http%3A%2F%2Flocalhost%3A8080%2Foauth2callback访问授权页面;
|
||||
2、该控制器首先检查clientId是否正确;如果错误将返回相应的错误信息;
|
||||
3、然后判断用户是否登录了,如果没有登录首先到登录页面登录;
|
||||
4、登录成功后生成相应的code即授权码,然后重定向到客户端地址,如http://localhost:8080/oauth2callback?code=6d250650831fea227749f49a5b49ccad;在重定向到的地址中会带上code参数(授权码),接着客户端可以根据授权码去换取accessToken。
|
||||
* </pre>
|
||||
*
|
||||
* @param request req
|
||||
* @param response resp
|
||||
* @param authConfig 配置
|
||||
* @return 返回响应内容
|
||||
* @throws URISyntaxException
|
||||
* @throws OAuthSystemException
|
||||
*/
|
||||
OAuthResponse authorize(HttpServletRequest request, HttpServletResponse response, OAuth2Config authConfig)
|
||||
throws URISyntaxException, OAuthSystemException;
|
||||
|
||||
|
||||
/**
|
||||
* 通过code获取accessToken.
|
||||
* @param fetchTokenParam
|
||||
* @param authConfig 配置项
|
||||
* @return 返回响应内容
|
||||
* @throws URISyntaxException
|
||||
* @throws OAuthSystemException
|
||||
*/
|
||||
FetchTokenResult accessToken(FetchTokenParam fetchTokenParam, OAuth2Config authConfig);
|
||||
}
|
@@ -0,0 +1,22 @@
|
||||
package com.gitee.sop.sopauth.auth;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 如果要使用oauth2功能,自己的用户类需要实现这个对象
|
||||
*
|
||||
* @author tanghc
|
||||
*/
|
||||
public interface OpenUser extends Serializable {
|
||||
/**
|
||||
* 返回用户id
|
||||
* @return
|
||||
*/
|
||||
String getUserId();
|
||||
/**
|
||||
* 返回用户名
|
||||
*
|
||||
* @return 返回用户名
|
||||
*/
|
||||
String getUsername();
|
||||
}
|
@@ -0,0 +1,40 @@
|
||||
package com.gitee.sop.sopauth.auth;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* @author tanghc
|
||||
*/
|
||||
public class RefreshToken implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private String accessToken;
|
||||
private OpenUser openUser;
|
||||
|
||||
public RefreshToken(String accessToken, OpenUser openUser) {
|
||||
super();
|
||||
this.accessToken = accessToken;
|
||||
this.openUser = openUser;
|
||||
}
|
||||
|
||||
public RefreshToken() {
|
||||
super();
|
||||
}
|
||||
|
||||
public String getAccessToken() {
|
||||
return accessToken;
|
||||
}
|
||||
|
||||
public void setAccessToken(String accessToken) {
|
||||
this.accessToken = accessToken;
|
||||
}
|
||||
|
||||
public OpenUser getOpenUser() {
|
||||
return openUser;
|
||||
}
|
||||
|
||||
public void setOpenUser(OpenUser openUser) {
|
||||
this.openUser = openUser;
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,29 @@
|
||||
package com.gitee.sop.sopauth.auth;
|
||||
|
||||
/**
|
||||
* 存放accessToken和refreshToken
|
||||
*
|
||||
* @author tanghc
|
||||
*
|
||||
*/
|
||||
public class TokenPair {
|
||||
private String accessToken;
|
||||
private String refreshToken;
|
||||
|
||||
public String getAccessToken() {
|
||||
return accessToken;
|
||||
}
|
||||
|
||||
public void setAccessToken(String accessToken) {
|
||||
this.accessToken = accessToken;
|
||||
}
|
||||
|
||||
public String getRefreshToken() {
|
||||
return refreshToken;
|
||||
}
|
||||
|
||||
public void setRefreshToken(String refreshToken) {
|
||||
this.refreshToken = refreshToken;
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,25 @@
|
||||
package com.gitee.sop.sopauth.auth.exception;
|
||||
|
||||
/**
|
||||
* @author tanghc
|
||||
*/
|
||||
public class LoginErrorException extends Exception {
|
||||
private static final long serialVersionUID = -6721499454527023339L;
|
||||
|
||||
public LoginErrorException() {
|
||||
super();
|
||||
}
|
||||
|
||||
public LoginErrorException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
public LoginErrorException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public LoginErrorException(Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,33 @@
|
||||
package com.gitee.sop.sopauth.auth.impl;
|
||||
|
||||
import com.gitee.sop.sopauth.auth.AppIdManager;
|
||||
import com.gitee.sop.sopauth.entity.IsvInfo;
|
||||
import com.gitee.sop.sopauth.mapper.IsvInfoMapper;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* @author tanghc
|
||||
*/
|
||||
@Service
|
||||
@Slf4j
|
||||
public class AppIdManagerImpl implements AppIdManager {
|
||||
|
||||
public static final int FORBIDDEN = 2;
|
||||
@Autowired
|
||||
private IsvInfoMapper isvInfoMapper;
|
||||
|
||||
@Override
|
||||
public boolean isValidAppId(String appId) {
|
||||
IsvInfo isvInfo = isvInfoMapper.getByColumn("app_key", appId);
|
||||
if (isvInfo == null) {
|
||||
return false;
|
||||
}
|
||||
if (isvInfo.getStatus().intValue() == FORBIDDEN) {
|
||||
log.error("appId已禁用:{}", appId);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
@@ -0,0 +1,135 @@
|
||||
package com.gitee.sop.sopauth.auth.impl;
|
||||
|
||||
import com.gitee.fastmybatis.core.query.Query;
|
||||
import com.gitee.sop.sopauth.auth.OAuth2Config;
|
||||
import com.gitee.sop.sopauth.auth.OAuth2Manager;
|
||||
import com.gitee.sop.sopauth.auth.OpenUser;
|
||||
import com.gitee.sop.sopauth.auth.RefreshToken;
|
||||
import com.gitee.sop.sopauth.auth.exception.LoginErrorException;
|
||||
import com.gitee.sop.sopauth.entity.UserInfo;
|
||||
import com.gitee.sop.sopauth.mapper.UserInfoMapper;
|
||||
import com.google.common.cache.CacheBuilder;
|
||||
import com.google.common.cache.CacheLoader;
|
||||
import com.google.common.cache.LoadingCache;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* oauth2管理,默认谷歌缓存实现,跟redis实现只能用一个。正式环境推荐使用redis保存
|
||||
* @author tanghc
|
||||
*
|
||||
*/
|
||||
@Service
|
||||
public class OAuth2ManagerCache implements OAuth2Manager {
|
||||
/**
|
||||
* 应用授权的app_auth_code唯一的;app_auth_code使用一次后失效,一天(从生成app_auth_code开始的24小时)未被使用自动过期;
|
||||
* app_auth_token永久有效。
|
||||
*/
|
||||
private int codeTimeoutSeconds = OAuth2Config.getInstance().getCodeTimeoutSeconds();
|
||||
/**
|
||||
* accessToken过期时间
|
||||
* -1 永久有效
|
||||
*/
|
||||
private int accessTokenTimeoutSeconds = OAuth2Config.getInstance().getAccessTokenExpiresIn();
|
||||
|
||||
private int refreshTokenTimeoutSeconds = OAuth2Config.getInstance().getRefreshTokenExpiresIn();
|
||||
|
||||
private LoadingCache<String, OpenUser> codeCache = buildCache(codeTimeoutSeconds);
|
||||
private LoadingCache<String, OpenUser> accessTokenCache = buildCache(accessTokenTimeoutSeconds);
|
||||
private LoadingCache<String, RefreshToken> refreshTokenCache = buildCache(refreshTokenTimeoutSeconds);
|
||||
|
||||
@Autowired
|
||||
private UserInfoMapper userInfoMapper;
|
||||
|
||||
|
||||
private static <T> LoadingCache<String, T> buildCache(int timeout) {
|
||||
CacheBuilder<Object, Object> cacheBuilder = CacheBuilder.newBuilder();
|
||||
if (timeout > 0) {
|
||||
cacheBuilder.expireAfterAccess(timeout, TimeUnit.SECONDS);
|
||||
}
|
||||
return cacheBuilder
|
||||
.build(new CacheLoader<String, T>() {
|
||||
@Override
|
||||
public T load(String key) throws Exception {
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addAuthCode(String authCode, OpenUser authUser) {
|
||||
codeCache.put(authCode, authUser);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void addAccessToken(String accessToken, String refreshToken, OpenUser authUser) {
|
||||
accessTokenCache.put(accessToken, authUser);
|
||||
refreshTokenCache.put(refreshToken, new RefreshToken(accessToken, authUser));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeAccessToken(String accessToken) {
|
||||
accessTokenCache.asMap().remove(accessToken);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeRefreshToken(String refreshToken) {
|
||||
refreshTokenCache.asMap().remove(refreshToken);
|
||||
}
|
||||
|
||||
@Override
|
||||
public RefreshToken getRefreshToken(String refreshToken) {
|
||||
return refreshTokenCache.getIfPresent(refreshToken);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkAuthCode(String authCode) {
|
||||
return codeCache.asMap().containsKey(authCode);
|
||||
}
|
||||
|
||||
@Override
|
||||
public OpenUser getUserByAuthCode(String authCode) {
|
||||
return codeCache.getIfPresent(authCode);
|
||||
}
|
||||
|
||||
@Override
|
||||
public OpenUser getUserByAccessToken(String accessToken) {
|
||||
return accessTokenCache.getIfPresent(accessToken);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, String> getParam(OpenUser user) {
|
||||
Map<String, String> map = new HashMap<>();
|
||||
map.put("username", user.getUsername());
|
||||
return map;
|
||||
}
|
||||
|
||||
@Override
|
||||
public OpenUser login(HttpServletRequest request) throws LoginErrorException {
|
||||
// 这里应该先检查用户有没有登录,如果登录直接返回openUser
|
||||
String username = request.getParameter("username");
|
||||
String password = request.getParameter("password");
|
||||
if(StringUtils.isEmpty(username) || StringUtils.isEmpty(password)) {
|
||||
throw new LoginErrorException("用户名密码不能为空");
|
||||
}
|
||||
|
||||
Query query = new Query();
|
||||
query.eq("username", username)
|
||||
.eq("password", password);
|
||||
UserInfo userInfo = userInfoMapper.getByQuery(query);
|
||||
|
||||
if(userInfo == null) {
|
||||
throw new LoginErrorException("用户名密码不正确");
|
||||
}
|
||||
|
||||
return userInfo;
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,171 @@
|
||||
package com.gitee.sop.sopauth.auth.impl;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.gitee.fastmybatis.core.query.Query;
|
||||
import com.gitee.sop.sopauth.auth.OAuth2Config;
|
||||
import com.gitee.sop.sopauth.auth.OAuth2Manager;
|
||||
import com.gitee.sop.sopauth.auth.OpenUser;
|
||||
import com.gitee.sop.sopauth.auth.RefreshToken;
|
||||
import com.gitee.sop.sopauth.auth.exception.LoginErrorException;
|
||||
import com.gitee.sop.sopauth.entity.UserInfo;
|
||||
import com.gitee.sop.sopauth.mapper.UserInfoMapper;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.redis.core.StringRedisTemplate;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
*
|
||||
* oauth2管理redis实现,这个类跟OAuth2ManagerCache类只能用一个,
|
||||
* 如果要用这个类,注释掉OAuth2ManagerCache的@Service
|
||||
* 启用这个类的@Service
|
||||
*/
|
||||
//@Service
|
||||
public class OAuth2ManagerRedis implements OAuth2Manager {
|
||||
|
||||
private static String CODE_PREFIX = "com.gitee.sop.oauth2_code:";
|
||||
private static String ACCESS_TOKEN_PREFIX = "com.gitee.sop.oauth2_access_token:";
|
||||
private static String REFRESH_TOKEN_PREFIX = "com.gitee.sop.oauth2_refresh_token:";
|
||||
|
||||
private int codeTimeoutSeconds = OAuth2Config.getInstance().getCodeTimeoutSeconds();
|
||||
|
||||
@Autowired
|
||||
private StringRedisTemplate redisTemplate;
|
||||
|
||||
@Autowired
|
||||
private UserInfoMapper userInfoMapper;
|
||||
|
||||
public static String getCodeKey(String code) {
|
||||
return CODE_PREFIX + code;
|
||||
}
|
||||
|
||||
public static String getAccessTokenKey(String accessToken) {
|
||||
return ACCESS_TOKEN_PREFIX + accessToken;
|
||||
}
|
||||
|
||||
public static String getRefreshTokenKey(String refreshToken) {
|
||||
return REFRESH_TOKEN_PREFIX + refreshToken;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addAuthCode(String authCode, OpenUser authUser) {
|
||||
redisTemplate.opsForValue().set(getCodeKey(authCode),
|
||||
JSON.toJSONString(authUser),
|
||||
codeTimeoutSeconds,
|
||||
TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void addAccessToken(String accessToken, String refreshToken, OpenUser authUser) {
|
||||
// 存accessToken
|
||||
long expiresIn = OAuth2Config.getInstance().getAccessTokenExpiresIn();
|
||||
long reExpiresIn = OAuth2Config.getInstance().getRefreshTokenExpiresIn();
|
||||
if (expiresIn > 0) {
|
||||
redisTemplate.opsForValue().set(getAccessTokenKey(accessToken), JSON.toJSONString(authUser), expiresIn, TimeUnit.SECONDS);
|
||||
} else {
|
||||
redisTemplate.opsForValue().set(getAccessTokenKey(accessToken), JSON.toJSONString(authUser));
|
||||
}
|
||||
// 存refreshToken
|
||||
if (reExpiresIn > 0) {
|
||||
redisTemplate.opsForValue().set(
|
||||
getRefreshTokenKey(refreshToken),
|
||||
JSON.toJSONString(new RefreshToken(accessToken, authUser)),
|
||||
reExpiresIn, // refreshToken过期时间
|
||||
TimeUnit.SECONDS);
|
||||
} else {
|
||||
redisTemplate.opsForValue().set(
|
||||
getRefreshTokenKey(refreshToken),
|
||||
JSON.toJSONString(new RefreshToken(accessToken, authUser)));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeAccessToken(String accessToken) {
|
||||
String accessTokenKey = getAccessTokenKey(accessToken);
|
||||
int afterRefreshExpiresIn = OAuth2Config.getInstance().getAfterRefreshExpiresIn();
|
||||
redisTemplate.expire(accessTokenKey, afterRefreshExpiresIn, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeRefreshToken(String refreshToken) {
|
||||
redisTemplate.delete(getRefreshTokenKey(refreshToken));
|
||||
}
|
||||
|
||||
@Override
|
||||
public RefreshToken getRefreshToken(String refreshToken) {
|
||||
String json = redisTemplate.opsForValue().get(getRefreshTokenKey(refreshToken));
|
||||
if(StringUtils.isEmpty(json)) {
|
||||
return null;
|
||||
}
|
||||
JSONObject jsonObj = JSON.parseObject(json);
|
||||
|
||||
String userJson = jsonObj.getString("openUser");
|
||||
UserInfo user = JSON.parseObject(userJson, UserInfo.class);
|
||||
String accessToken = jsonObj.getString("accessToken");
|
||||
|
||||
return new RefreshToken(accessToken, user);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkAuthCode(String authCode) {
|
||||
if(StringUtils.isEmpty(authCode)) {
|
||||
return false;
|
||||
}
|
||||
return redisTemplate.hasKey(getCodeKey(authCode));
|
||||
}
|
||||
|
||||
@Override
|
||||
public OpenUser getUserByAuthCode(String authCode) {
|
||||
String json = redisTemplate.opsForValue().get(getCodeKey(authCode));
|
||||
if(StringUtils.isEmpty(json)) {
|
||||
return null;
|
||||
}
|
||||
return JSON.parseObject(json, UserInfo.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public OpenUser getUserByAccessToken(String accessToken) {
|
||||
String json = redisTemplate.opsForValue().get(getAccessTokenKey(accessToken));
|
||||
if(StringUtils.isEmpty(json)) {
|
||||
return null;
|
||||
}
|
||||
return JSON.parseObject(json, UserInfo.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, String> getParam(OpenUser user) {
|
||||
Map<String, String> map = new HashMap<>();
|
||||
map.put("username", user.getUsername());
|
||||
return map;
|
||||
}
|
||||
|
||||
@Override
|
||||
public OpenUser login(HttpServletRequest request) throws LoginErrorException {
|
||||
// 这里应该先检查用户有没有登录,如果登录直接返回openUser
|
||||
|
||||
String username = request.getParameter("username");
|
||||
String password = request.getParameter("password");
|
||||
if(StringUtils.isEmpty(username) || StringUtils.isEmpty(password)) {
|
||||
throw new LoginErrorException("用户名密码不能为空");
|
||||
}
|
||||
|
||||
Query query = new Query();
|
||||
query.eq("username", username)
|
||||
.eq("password", password);
|
||||
UserInfo userInfo = userInfoMapper.getByQuery(query);
|
||||
|
||||
if(userInfo == null) {
|
||||
throw new LoginErrorException("用户名密码不正确");
|
||||
}
|
||||
|
||||
return userInfo;
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,284 @@
|
||||
package com.gitee.sop.sopauth.auth.impl;
|
||||
|
||||
import com.gitee.sop.sopauth.auth.AppIdManager;
|
||||
import com.gitee.sop.sopauth.auth.FetchTokenParam;
|
||||
import com.gitee.sop.sopauth.auth.FetchTokenResult;
|
||||
import com.gitee.sop.sopauth.auth.OAuth2Config;
|
||||
import com.gitee.sop.sopauth.auth.OAuth2Manager;
|
||||
import com.gitee.sop.sopauth.auth.OAuth2Service;
|
||||
import com.gitee.sop.sopauth.auth.OpenUser;
|
||||
import com.gitee.sop.sopauth.auth.RefreshToken;
|
||||
import com.gitee.sop.sopauth.auth.TokenPair;
|
||||
import com.gitee.sop.sopauth.auth.exception.LoginErrorException;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.oltu.oauth2.as.issuer.MD5Generator;
|
||||
import org.apache.oltu.oauth2.as.issuer.OAuthIssuer;
|
||||
import org.apache.oltu.oauth2.as.issuer.OAuthIssuerImpl;
|
||||
import org.apache.oltu.oauth2.as.request.OAuthAuthzRequest;
|
||||
import org.apache.oltu.oauth2.as.response.OAuthASResponse;
|
||||
import org.apache.oltu.oauth2.as.response.OAuthASResponse.OAuthTokenResponseBuilder;
|
||||
import org.apache.oltu.oauth2.common.OAuth;
|
||||
import org.apache.oltu.oauth2.common.error.OAuthError;
|
||||
import org.apache.oltu.oauth2.common.exception.OAuthProblemException;
|
||||
import org.apache.oltu.oauth2.common.exception.OAuthSystemException;
|
||||
import org.apache.oltu.oauth2.common.message.OAuthResponse;
|
||||
import org.apache.oltu.oauth2.common.message.types.GrantType;
|
||||
import org.apache.oltu.oauth2.common.message.types.ResponseType;
|
||||
import org.apache.oltu.oauth2.common.utils.OAuthUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* oauth2服务端默认实现
|
||||
*
|
||||
* @author tanghc
|
||||
*/
|
||||
@Service
|
||||
@Slf4j
|
||||
public class OAuth2ServiceImpl implements OAuth2Service {
|
||||
|
||||
|
||||
private static final String TOKEN_TYPE = "Bearer";
|
||||
|
||||
private OAuthIssuer oauthIssuer = new OAuthIssuerImpl(new MD5Generator());
|
||||
|
||||
@Autowired
|
||||
private OAuth2Manager oauth2Manager;
|
||||
|
||||
@Autowired
|
||||
private AppIdManager appIdManager;
|
||||
|
||||
@Override
|
||||
public OAuthResponse authorize(HttpServletRequest request, HttpServletResponse resp, OAuth2Config authConfig)
|
||||
throws URISyntaxException, OAuthSystemException {
|
||||
try {
|
||||
// 构建OAuth 授权请求
|
||||
OAuthAuthzRequest oauthRequest = new OAuthAuthzRequest(request);
|
||||
String clientId = oauthRequest.getClientId();
|
||||
// 检查传入的客户端id是否正确
|
||||
if (!appIdManager.isValidAppId(clientId)) {
|
||||
return OAuthASResponse.errorResponse(HttpServletResponse.SC_BAD_REQUEST)
|
||||
.setError(OAuthError.TokenResponse.INVALID_CLIENT)
|
||||
.setErrorDescription(OAuthError.TokenResponse.INVALID_CLIENT).buildJSONMessage();
|
||||
}
|
||||
|
||||
// 如果用户没有登录,跳转到登陆页面
|
||||
OpenUser user = null;
|
||||
try {
|
||||
user = oauth2Manager.login(request);
|
||||
} catch (LoginErrorException e) {
|
||||
log.error(e.getMessage(), e);
|
||||
request.setAttribute("error", e.getMessage());
|
||||
try {
|
||||
request.getRequestDispatcher(authConfig.getOauth2LoginUri()).forward(request, resp);
|
||||
return null;
|
||||
} catch (Exception e1) {
|
||||
log.error(e1.getMessage(), e1);
|
||||
throw new RuntimeException(e1);
|
||||
}
|
||||
}
|
||||
|
||||
// 生成授权码
|
||||
String authorizationCode = null;
|
||||
// responseType目前仅支持CODE,另外还有TOKEN
|
||||
String responseType = oauthRequest.getParam(OAuth.OAUTH_RESPONSE_TYPE);
|
||||
if (responseType.equals(ResponseType.CODE.toString())) {
|
||||
OAuthIssuerImpl oauthIssuerImpl = new OAuthIssuerImpl(new MD5Generator());
|
||||
authorizationCode = oauthIssuerImpl.authorizationCode();
|
||||
oauth2Manager.addAuthCode(authorizationCode, user);
|
||||
}
|
||||
// 进行OAuth响应构建
|
||||
OAuthASResponse.OAuthAuthorizationResponseBuilder builder = OAuthASResponse.authorizationResponse(request,
|
||||
HttpServletResponse.SC_FOUND);
|
||||
// 设置授权码
|
||||
builder.setCode(authorizationCode);
|
||||
// 得到到客户端重定向地址
|
||||
String redirectURI = oauthRequest.getParam(OAuth.OAUTH_REDIRECT_URI);
|
||||
|
||||
// 构建响应
|
||||
return builder.location(redirectURI).buildQueryMessage();
|
||||
} catch (OAuthProblemException e) {
|
||||
// 出错处理
|
||||
String redirectUri = e.getRedirectUri();
|
||||
if (OAuthUtils.isEmpty(redirectUri)) {
|
||||
// 告诉客户端没有传入redirectUri直接报错
|
||||
String error = "OAuth redirectUri needs to be provided by client!!!";
|
||||
return OAuthASResponse.errorResponse(HttpServletResponse.SC_FOUND)
|
||||
.error(OAuthProblemException.error(error)).location(redirectUri).buildQueryMessage();
|
||||
} else {
|
||||
// 返回错误消息(如?error=)
|
||||
return OAuthASResponse.errorResponse(HttpServletResponse.SC_FOUND).error(e).location(redirectUri)
|
||||
.buildQueryMessage();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public FetchTokenResult accessToken(FetchTokenParam fetchTokenParam, OAuth2Config authConfig) {
|
||||
try {
|
||||
// 这里需要检查client_id和client_secret,但是已经通过网关接口访问进来了
|
||||
// 表示client_id和client_secret是合法的
|
||||
|
||||
// 检查验证类型,如果是第一次进来用code换取accessToken
|
||||
String grant_type = fetchTokenParam.getGrant_type();
|
||||
if (GrantType.AUTHORIZATION_CODE.toString().equals(grant_type)) {
|
||||
String authCode = fetchTokenParam.getCode();
|
||||
if (!oauth2Manager.checkAuthCode(authCode)) {
|
||||
FetchTokenResult errorResult = new FetchTokenResult();
|
||||
errorResult.setError(OAuthError.CodeResponse.INVALID_REQUEST);
|
||||
errorResult.setError_description("invalid request");
|
||||
return errorResult;
|
||||
}
|
||||
// 生成Access Token
|
||||
OpenUser user = oauth2Manager.getUserByAuthCode(authCode);
|
||||
if (user == null) {
|
||||
throw OAuthProblemException.error("Can not found user by code.");
|
||||
}
|
||||
|
||||
TokenPair tokenPair = this.createNewToken(user);
|
||||
|
||||
oauth2Manager.addAccessToken(tokenPair.getAccessToken(), tokenPair.getRefreshToken(), user);
|
||||
|
||||
// 生成OAuth响应
|
||||
return this.buildTokenResult(tokenPair, user);
|
||||
} else if (GrantType.REFRESH_TOKEN.toString().equals(grant_type)) {
|
||||
// 用refreshToken来刷新accessToken
|
||||
String refreshToken = fetchTokenParam.getRefresh_token();
|
||||
if (StringUtils.isEmpty(refreshToken)) {
|
||||
FetchTokenResult errorResult = new FetchTokenResult();
|
||||
errorResult.setError(OAuthError.ResourceResponse.EXPIRED_TOKEN);
|
||||
errorResult.setError_description("expired token");
|
||||
return errorResult;
|
||||
}
|
||||
|
||||
RefreshToken refreshTokenObj = oauth2Manager.getRefreshToken(refreshToken);
|
||||
if (refreshTokenObj == null) {
|
||||
FetchTokenResult errorResult = new FetchTokenResult();
|
||||
errorResult.setError(OAuthError.ResourceResponse.INVALID_TOKEN);
|
||||
errorResult.setError_description("invalid token");
|
||||
return errorResult;
|
||||
}
|
||||
|
||||
OpenUser user = refreshTokenObj.getOpenUser();
|
||||
// 老的token对
|
||||
TokenPair oldTokenPair = new TokenPair();
|
||||
oldTokenPair.setAccessToken(refreshTokenObj.getAccessToken());
|
||||
oldTokenPair.setRefreshToken(refreshToken);
|
||||
// 创建一对新的accessToken和refreshToken
|
||||
TokenPair newTokenPair = this.createRefreshToken(user, oldTokenPair);
|
||||
|
||||
this.afterRefreshToken(oldTokenPair, newTokenPair, user);
|
||||
|
||||
// 返回新的accessToken和refreshToken
|
||||
return this.buildTokenResult(newTokenPair, user);
|
||||
} else {
|
||||
FetchTokenResult errorResult = new FetchTokenResult();
|
||||
errorResult.setError(OAuthError.TokenResponse.INVALID_GRANT);
|
||||
errorResult.setError_description("invalid grant");
|
||||
return errorResult;
|
||||
}
|
||||
|
||||
} catch (OAuthProblemException e) {
|
||||
log.error(e.getMessage(), e);
|
||||
FetchTokenResult errorResult = new FetchTokenResult();
|
||||
errorResult.setError(e.getMessage());
|
||||
errorResult.setError_description("invalid grant");
|
||||
return errorResult;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 刷新token后续操作
|
||||
*
|
||||
* @param oldTokenPair 老的token
|
||||
* @param newTokenPair 新的token
|
||||
* @param user 用户
|
||||
*/
|
||||
protected void afterRefreshToken(TokenPair oldTokenPair, TokenPair newTokenPair, OpenUser user) {
|
||||
// 保存token
|
||||
oauth2Manager.addAccessToken(newTokenPair.getAccessToken(), newTokenPair.getRefreshToken(), user);
|
||||
|
||||
// 删除老的accessToken
|
||||
oauth2Manager.removeAccessToken(oldTokenPair.getAccessToken());
|
||||
// 删除老的refreshToken
|
||||
oauth2Manager.removeRefreshToken(oldTokenPair.getRefreshToken());
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建新的token
|
||||
*
|
||||
* @param user
|
||||
* @return 返回新token
|
||||
*/
|
||||
protected TokenPair createNewToken(OpenUser user) {
|
||||
return this.createDefaultTokenPair();
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回刷新后token
|
||||
*
|
||||
* @param user 用户
|
||||
* @param oldTokenPair 旧的token
|
||||
* @return 返回新的token
|
||||
*/
|
||||
protected TokenPair createRefreshToken(OpenUser user, TokenPair oldTokenPair) {
|
||||
return this.createDefaultTokenPair();
|
||||
}
|
||||
|
||||
private TokenPair createDefaultTokenPair() {
|
||||
TokenPair tokenPair = new TokenPair();
|
||||
try {
|
||||
String accessToken = oauthIssuer.accessToken();
|
||||
String refreshToken = oauthIssuer.refreshToken();
|
||||
|
||||
tokenPair.setAccessToken(accessToken);
|
||||
tokenPair.setRefreshToken(refreshToken);
|
||||
|
||||
return tokenPair;
|
||||
} catch (OAuthSystemException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private FetchTokenResult buildTokenResult(TokenPair tokenPair, OpenUser user) {
|
||||
OAuth2Config auth2Config = OAuth2Config.getInstance();
|
||||
FetchTokenResult fetchTokenResult = new FetchTokenResult();
|
||||
fetchTokenResult.setApp_auth_token(tokenPair.getAccessToken());
|
||||
fetchTokenResult.setApp_refresh_token(tokenPair.getRefreshToken());
|
||||
fetchTokenResult.setUser_id(user.getUserId());
|
||||
fetchTokenResult.setExpires_in(auth2Config.getAccessTokenExpiresIn());
|
||||
fetchTokenResult.setRe_expires_in(auth2Config.getRefreshTokenExpiresIn());
|
||||
return fetchTokenResult;
|
||||
}
|
||||
|
||||
private OAuthResponse buildAccessTokenResponse(TokenPair tokenPair, long expiresIn, OpenUser user) throws OAuthSystemException {
|
||||
OAuthTokenResponseBuilder resp = OAuthASResponse.tokenResponse(HttpServletResponse.SC_OK);
|
||||
|
||||
Map<String, String> param = oauth2Manager.getParam(user);
|
||||
if (param != null) {
|
||||
Set<Entry<String, String>> entrySet = param.entrySet();
|
||||
for (Entry<String, String> entry : entrySet) {
|
||||
resp.setParam(entry.getKey(), entry.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
return resp
|
||||
.setAccessToken(tokenPair.getAccessToken())
|
||||
.setRefreshToken(tokenPair.getRefreshToken())
|
||||
.setTokenType(TOKEN_TYPE)
|
||||
.setExpiresIn(String.valueOf(expiresIn))
|
||||
.buildJSONMessage();
|
||||
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,20 @@
|
||||
package com.gitee.sop.sopauth.config;
|
||||
|
||||
import com.gitee.sop.servercommon.bean.ServiceConfig;
|
||||
import com.gitee.sop.servercommon.configuration.AlipayServiceConfiguration;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
/**
|
||||
* 使用支付宝开放平台功能
|
||||
*
|
||||
* @author tanghc
|
||||
*/
|
||||
@Configuration
|
||||
public class OpenServiceConfig extends AlipayServiceConfiguration {
|
||||
|
||||
|
||||
static {
|
||||
ServiceConfig.getInstance().getI18nModules().add("i18n/isp/goods_error");
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,54 @@
|
||||
package com.gitee.sop.sopauth.controller;
|
||||
|
||||
import com.gitee.sop.sdk.client.OpenClient;
|
||||
import com.gitee.sop.sdk.model.OpenAuthTokenAppModel;
|
||||
import com.gitee.sop.sdk.request.OpenAuthTokenAppRequest;
|
||||
import com.gitee.sop.sdk.response.OpenAuthTokenAppResponse;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
/**
|
||||
* @author tanghc
|
||||
*/
|
||||
@Controller
|
||||
@Slf4j
|
||||
public class CallbackController {
|
||||
String url = "http://localhost:8081/api"; // zuul
|
||||
String appId = "2019032617262200001";
|
||||
// 支付宝私钥
|
||||
String privateKey = "MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCXJv1pQFqWNA/++OYEV7WYXwexZK/J8LY1OWlP9X0T6wHFOvxNKRvMkJ5544SbgsJpVcvRDPrcxmhPbi/sAhdO4x2PiPKIz9Yni2OtYCCeaiE056B+e1O2jXoLeXbfi9fPivJZkxH/tb4xfLkH3bA8ZAQnQsoXA0SguykMRZntF0TndUfvDrLqwhlR8r5iRdZLB6F8o8qXH6UPDfNEnf/K8wX5T4EB1b8x8QJ7Ua4GcIUqeUxGHdQpzNbJdaQvoi06lgccmL+PHzminkFYON7alj1CjDN833j7QMHdPtS9l7B67fOU/p2LAAkPMtoVBfxQt9aFj7B8rEhGCz02iJIBAgMBAAECggEARqOuIpY0v6WtJBfmR3lGIOOokLrhfJrGTLF8CiZMQha+SRJ7/wOLPlsH9SbjPlopyViTXCuYwbzn2tdABigkBHYXxpDV6CJZjzmRZ+FY3S/0POlTFElGojYUJ3CooWiVfyUMhdg5vSuOq0oCny53woFrf32zPHYGiKdvU5Djku1onbDU0Lw8w+5tguuEZ76kZ/lUcccGy5978FFmYpzY/65RHCpvLiLqYyWTtaNT1aQ/9pw4jX9HO9NfdJ9gYFK8r/2f36ZE4hxluAfeOXQfRC/WhPmiw/ReUhxPznG/WgKaa/OaRtAx3inbQ+JuCND7uuKeRe4osP2jLPHPP6AUwQKBgQDUNu3BkLoKaimjGOjCTAwtp71g1oo+k5/uEInAo7lyEwpV0EuUMwLA/HCqUgR4K9pyYV+Oyb8d6f0+Hz0BMD92I2pqlXrD7xV2WzDvyXM3s63NvorRooKcyfd9i6ccMjAyTR2qfLkxv0hlbBbsPHz4BbU63xhTJp3Ghi0/ey/1HQKBgQC2VsgqC6ykfSidZUNLmQZe3J0p/Qf9VLkfrQ+xaHapOs6AzDU2H2osuysqXTLJHsGfrwVaTs00ER2z8ljTJPBUtNtOLrwNRlvgdnzyVAKHfOgDBGwJgiwpeE9voB1oAV/mXqSaUWNnuwlOIhvQEBwekqNyWvhLqC7nCAIhj3yvNQKBgQCqYbeec56LAhWP903Zwcj9VvG7sESqXUhIkUqoOkuIBTWFFIm54QLTA1tJxDQGb98heoCIWf5x/A3xNI98RsqNBX5JON6qNWjb7/dobitti3t99v/ptDp9u8JTMC7penoryLKK0Ty3bkan95Kn9SC42YxaSghzqkt+uvfVQgiNGQKBgGxU6P2aDAt6VNwWosHSe+d2WWXt8IZBhO9d6dn0f7ORvcjmCqNKTNGgrkewMZEuVcliueJquR47IROdY8qmwqcBAN7Vg2K7r7CPlTKAWTRYMJxCT1Hi5gwJb+CZF3+IeYqsJk2NF2s0w5WJTE70k1BSvQsfIzAIDz2yE1oPHvwVAoGAA6e+xQkVH4fMEph55RJIZ5goI4Y76BSvt2N5OKZKd4HtaV+eIhM3SDsVYRLIm9ZquJHMiZQGyUGnsvrKL6AAVNK7eQZCRDk9KQz+0GKOGqku0nOZjUbAu6A2/vtXAaAuFSFx1rUQVVjFulLexkXR3KcztL1Qu2k5pB6Si0K/uwQ=";
|
||||
|
||||
OpenClient openClient = new OpenClient(url, appId, privateKey);
|
||||
|
||||
/**
|
||||
* 模拟开发者回调,这里需要开发者自己实现.通过code换取token
|
||||
* @return
|
||||
*/
|
||||
@GetMapping("oauth2callback")
|
||||
@ResponseBody
|
||||
public String callback(HttpServletRequest servletRequest, HttpServletResponse servletResponse) {
|
||||
servletResponse.setCharacterEncoding("UTF-8");
|
||||
String app_id = servletRequest.getParameter("app_id");
|
||||
String code = servletRequest.getParameter("code");
|
||||
|
||||
OpenAuthTokenAppRequest request = new OpenAuthTokenAppRequest();
|
||||
OpenAuthTokenAppModel model = new OpenAuthTokenAppModel();
|
||||
model.setCode(code);
|
||||
model.setGrant_type("authorization_code");
|
||||
request.setBizModel(model);
|
||||
|
||||
// 根据code获取token
|
||||
OpenAuthTokenAppResponse response = openClient.execute(request);
|
||||
if (response.isSuccess()) {
|
||||
// 成功拿到token,开发者在这里保存token信息
|
||||
// 后续使用token进行接口访问
|
||||
log.info("授权成功,body:{}", response.getBody());
|
||||
}
|
||||
return response.getBody();
|
||||
}
|
||||
}
|
@@ -0,0 +1,85 @@
|
||||
package com.gitee.sop.sopauth.controller;
|
||||
|
||||
import com.gitee.sop.servercommon.annotation.ApiMapping;
|
||||
import com.gitee.sop.sopauth.auth.FetchTokenParam;
|
||||
import com.gitee.sop.sopauth.auth.FetchTokenResult;
|
||||
import com.gitee.sop.sopauth.auth.OAuth2Config;
|
||||
import com.gitee.sop.sopauth.auth.OAuth2Service;
|
||||
import org.apache.oltu.oauth2.common.exception.OAuthSystemException;
|
||||
import org.apache.oltu.oauth2.common.message.OAuthResponse;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.ModelMap;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
|
||||
/**
|
||||
* 授权认证
|
||||
*/
|
||||
@Controller
|
||||
@RequestMapping("oauth2")
|
||||
public class OAuth2Controller {
|
||||
|
||||
@Autowired
|
||||
private OAuth2Service oAuth2Service;
|
||||
|
||||
// 第一步:授权URL拼装
|
||||
// https://localhost:8087/oauth2/appToAppAuth?app_id=2019032617262200001&redirect_uri=http%3a%2f%2flocalhost%3a8087%2foauth2callback
|
||||
@GetMapping("appToAppAuth")
|
||||
public String appToAppAuth(HttpServletRequest request, ModelMap modelMap) {
|
||||
String app_id = request.getParameter("app_id");
|
||||
String redirect_uri = request.getParameter("redirect_uri");
|
||||
modelMap.put("response_type", "code");
|
||||
modelMap.put("client_id", app_id);
|
||||
modelMap.put("redirect_uri", redirect_uri);
|
||||
return "oauth2login";
|
||||
}
|
||||
|
||||
/**
|
||||
* 第二步:点击登录,到这里拿code
|
||||
* oauth2认证获取code
|
||||
* @param request
|
||||
* @param resp
|
||||
* @return 返回code
|
||||
* @throws URISyntaxException
|
||||
* @throws OAuthSystemException
|
||||
*/
|
||||
@RequestMapping("authorize")
|
||||
public Object authorize(HttpServletRequest request, HttpServletResponse resp) throws URISyntaxException, OAuthSystemException {
|
||||
OAuthResponse response = oAuth2Service.authorize(request, resp, OAuth2Config.getInstance());
|
||||
if(response == null) {
|
||||
return null;
|
||||
}
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.setLocation(new URI(response.getLocationUri()));
|
||||
return new ResponseEntity<String>(headers, HttpStatus.valueOf(response.getResponseStatus()));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 第三步,通过code获取token
|
||||
* 或者,通过refresh_token换取token
|
||||
* @param param
|
||||
* @return
|
||||
*/
|
||||
@ApiMapping("open.auth.token.app")
|
||||
@ResponseBody
|
||||
public FetchTokenResult fetchToken(FetchTokenParam param) {
|
||||
FetchTokenResult fetchTokenResult = oAuth2Service.accessToken(param, OAuth2Config.getInstance());
|
||||
return fetchTokenResult;
|
||||
}
|
||||
|
||||
@RequestMapping("login")
|
||||
public String oauth2login() {
|
||||
return "oauth2login";
|
||||
}
|
||||
}
|
@@ -0,0 +1,32 @@
|
||||
package com.gitee.sop.sopauth.entity;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.GenerationType;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Table;
|
||||
|
||||
|
||||
/**
|
||||
* 表名:isv_info
|
||||
* 备注:isv信息表
|
||||
*
|
||||
* @author tanghc
|
||||
*/
|
||||
@Table(name = "isv_info")
|
||||
@Data
|
||||
public class IsvInfo {
|
||||
@Id
|
||||
@Column(name = "id")
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
/** 数据库字段:id */
|
||||
private Long id;
|
||||
|
||||
/** appKey, 数据库字段:app_key */
|
||||
private String appKey;
|
||||
|
||||
/** 1启用,2禁用, 数据库字段:status */
|
||||
private Byte status;
|
||||
}
|
@@ -0,0 +1,48 @@
|
||||
package com.gitee.sop.sopauth.entity;
|
||||
|
||||
import com.gitee.sop.sopauth.auth.OpenUser;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.GenerationType;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Table;
|
||||
import java.util.Date;
|
||||
|
||||
|
||||
/**
|
||||
* 表名:user_info
|
||||
* 备注:用户信息表
|
||||
*
|
||||
* @author tanghc
|
||||
*/
|
||||
@Table(name = "user_info")
|
||||
@Data
|
||||
public class UserInfo implements OpenUser {
|
||||
@Id
|
||||
@Column(name = "id")
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
/** 数据库字段:id */
|
||||
private Long id;
|
||||
|
||||
/** 用户名, 数据库字段:username */
|
||||
private String username;
|
||||
|
||||
/** 密码, 数据库字段:password */
|
||||
private String password;
|
||||
|
||||
/** 昵称, 数据库字段:nickname */
|
||||
private String nickname;
|
||||
|
||||
/** 数据库字段:gmt_create */
|
||||
private Date gmtCreate;
|
||||
|
||||
/** 数据库字段:gmt_modified */
|
||||
private Date gmtModified;
|
||||
|
||||
@Override
|
||||
public String getUserId() {
|
||||
return String.valueOf(id);
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
package com.gitee.sop.sopauth.mapper;
|
||||
|
||||
import com.gitee.fastmybatis.core.mapper.CrudMapper;
|
||||
import com.gitee.sop.sopauth.entity.IsvInfo;
|
||||
|
||||
|
||||
/**
|
||||
* @author tanghc
|
||||
*/
|
||||
public interface IsvInfoMapper extends CrudMapper<IsvInfo, Long> {
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
package com.gitee.sop.sopauth.mapper;
|
||||
|
||||
import com.gitee.fastmybatis.core.mapper.CrudMapper;
|
||||
import com.gitee.sop.sopauth.entity.UserInfo;
|
||||
|
||||
|
||||
/**
|
||||
* @author tanghc
|
||||
*/
|
||||
public interface UserInfoMapper extends CrudMapper<UserInfo, Long> {
|
||||
}
|
35
sop-example/sop-auth/src/main/resources/application-dev.yml
Normal file
35
sop-example/sop-auth/src/main/resources/application-dev.yml
Normal file
@@ -0,0 +1,35 @@
|
||||
|
||||
server:
|
||||
port: 8087
|
||||
|
||||
|
||||
# 注册中心
|
||||
eureka:
|
||||
port: 1111
|
||||
host: localhost
|
||||
client:
|
||||
serviceUrl:
|
||||
defaultZone: http://${eureka.host}:${eureka.port}/eureka/
|
||||
|
||||
spring:
|
||||
application:
|
||||
name: sop-auth
|
||||
|
||||
cloud:
|
||||
zookeeper:
|
||||
connect-string: localhost:2181
|
||||
|
||||
# 数据源
|
||||
datasource:
|
||||
driver-class-name: com.mysql.jdbc.Driver
|
||||
url: jdbc:mysql://localhost:3306/sop?useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull
|
||||
username: root
|
||||
password: root
|
||||
|
||||
thymeleaf:
|
||||
cache: false
|
||||
|
||||
logging:
|
||||
level:
|
||||
com:
|
||||
gitee: debug
|
3
sop-example/sop-auth/src/main/resources/application.yml
Normal file
3
sop-example/sop-auth/src/main/resources/application.yml
Normal file
@@ -0,0 +1,3 @@
|
||||
spring:
|
||||
profiles:
|
||||
active: dev
|
@@ -0,0 +1,19 @@
|
||||
<!DOCTYPE html>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml"
|
||||
xmlns:th="http://www.thymeleaf.org"
|
||||
xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity3">
|
||||
<head>
|
||||
<title>用户登录</title>
|
||||
</head>
|
||||
<body>
|
||||
<div th:if="${error}" style="color: red;"><span th:text="${error}"></span></div>
|
||||
<form th:action="@{/oauth2/authorize}" method="post">
|
||||
<input name="response_type" type="hidden" th:value="${response_type}"/>
|
||||
<input name="client_id" type="hidden" th:value="${client_id}"/>
|
||||
<input name="redirect_uri" type="hidden" th:value="${redirect_uri}"/>
|
||||
用户名: <input type="text" name="username" value="zhangsan"/> <br/>
|
||||
密码: <input type="password" name="password" value="123456"/> <br/>
|
||||
<button type="submit">登录并授权</button>
|
||||
</form>
|
||||
</body>
|
||||
</html>
|
@@ -0,0 +1,40 @@
|
||||
package com.gitee.sop.sopauth;
|
||||
|
||||
import com.gitee.sop.sdk.client.OpenClient;
|
||||
import com.gitee.sop.sdk.model.OpenAuthTokenAppModel;
|
||||
import com.gitee.sop.sdk.request.OpenAuthTokenAppRequest;
|
||||
import com.gitee.sop.sdk.response.OpenAuthTokenAppResponse;
|
||||
import junit.framework.TestCase;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
/**
|
||||
* @author tanghc
|
||||
*/
|
||||
@Slf4j
|
||||
public class RefreshTokenTest extends TestCase {
|
||||
String url = "http://localhost:8081/api"; // zuul
|
||||
String appId = "2019032617262200001";
|
||||
// 支付宝私钥
|
||||
String privateKey = "MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCXJv1pQFqWNA/++OYEV7WYXwexZK/J8LY1OWlP9X0T6wHFOvxNKRvMkJ5544SbgsJpVcvRDPrcxmhPbi/sAhdO4x2PiPKIz9Yni2OtYCCeaiE056B+e1O2jXoLeXbfi9fPivJZkxH/tb4xfLkH3bA8ZAQnQsoXA0SguykMRZntF0TndUfvDrLqwhlR8r5iRdZLB6F8o8qXH6UPDfNEnf/K8wX5T4EB1b8x8QJ7Ua4GcIUqeUxGHdQpzNbJdaQvoi06lgccmL+PHzminkFYON7alj1CjDN833j7QMHdPtS9l7B67fOU/p2LAAkPMtoVBfxQt9aFj7B8rEhGCz02iJIBAgMBAAECggEARqOuIpY0v6WtJBfmR3lGIOOokLrhfJrGTLF8CiZMQha+SRJ7/wOLPlsH9SbjPlopyViTXCuYwbzn2tdABigkBHYXxpDV6CJZjzmRZ+FY3S/0POlTFElGojYUJ3CooWiVfyUMhdg5vSuOq0oCny53woFrf32zPHYGiKdvU5Djku1onbDU0Lw8w+5tguuEZ76kZ/lUcccGy5978FFmYpzY/65RHCpvLiLqYyWTtaNT1aQ/9pw4jX9HO9NfdJ9gYFK8r/2f36ZE4hxluAfeOXQfRC/WhPmiw/ReUhxPznG/WgKaa/OaRtAx3inbQ+JuCND7uuKeRe4osP2jLPHPP6AUwQKBgQDUNu3BkLoKaimjGOjCTAwtp71g1oo+k5/uEInAo7lyEwpV0EuUMwLA/HCqUgR4K9pyYV+Oyb8d6f0+Hz0BMD92I2pqlXrD7xV2WzDvyXM3s63NvorRooKcyfd9i6ccMjAyTR2qfLkxv0hlbBbsPHz4BbU63xhTJp3Ghi0/ey/1HQKBgQC2VsgqC6ykfSidZUNLmQZe3J0p/Qf9VLkfrQ+xaHapOs6AzDU2H2osuysqXTLJHsGfrwVaTs00ER2z8ljTJPBUtNtOLrwNRlvgdnzyVAKHfOgDBGwJgiwpeE9voB1oAV/mXqSaUWNnuwlOIhvQEBwekqNyWvhLqC7nCAIhj3yvNQKBgQCqYbeec56LAhWP903Zwcj9VvG7sESqXUhIkUqoOkuIBTWFFIm54QLTA1tJxDQGb98heoCIWf5x/A3xNI98RsqNBX5JON6qNWjb7/dobitti3t99v/ptDp9u8JTMC7penoryLKK0Ty3bkan95Kn9SC42YxaSghzqkt+uvfVQgiNGQKBgGxU6P2aDAt6VNwWosHSe+d2WWXt8IZBhO9d6dn0f7ORvcjmCqNKTNGgrkewMZEuVcliueJquR47IROdY8qmwqcBAN7Vg2K7r7CPlTKAWTRYMJxCT1Hi5gwJb+CZF3+IeYqsJk2NF2s0w5WJTE70k1BSvQsfIzAIDz2yE1oPHvwVAoGAA6e+xQkVH4fMEph55RJIZ5goI4Y76BSvt2N5OKZKd4HtaV+eIhM3SDsVYRLIm9ZquJHMiZQGyUGnsvrKL6AAVNK7eQZCRDk9KQz+0GKOGqku0nOZjUbAu6A2/vtXAaAuFSFx1rUQVVjFulLexkXR3KcztL1Qu2k5pB6Si0K/uwQ=";
|
||||
|
||||
OpenClient openClient = new OpenClient(url, appId, privateKey);
|
||||
|
||||
/**
|
||||
* 根据refreshToken换取token
|
||||
*/
|
||||
public void testRefreshToken() {
|
||||
OpenAuthTokenAppRequest request = new OpenAuthTokenAppRequest();
|
||||
OpenAuthTokenAppModel model = new OpenAuthTokenAppModel();
|
||||
model.setGrant_type("refresh_token");
|
||||
model.setRefresh_token("856faf8d77d3b985c1073557ce6ea724");
|
||||
request.setBizModel(model);
|
||||
|
||||
OpenAuthTokenAppResponse response = openClient.execute(request);
|
||||
if (response.isSuccess()) {
|
||||
// 成功拿到token,开发者在这里保存token信息
|
||||
// 后续使用token进行接口访问
|
||||
log.info("换取token成功,body:{}", response.getBody());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,16 @@
|
||||
package com.gitee.sop.sopauth;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest
|
||||
public class SopAuthApplicationTests {
|
||||
|
||||
@Test
|
||||
public void contextLoads() {
|
||||
}
|
||||
|
||||
}
|
@@ -23,7 +23,7 @@
|
||||
<dependency>
|
||||
<groupId>com.gitee.sop</groupId>
|
||||
<artifactId>sop-service-common</artifactId>
|
||||
<version>1.5.0-SNAPSHOT</version>
|
||||
<version>1.6.0-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.gitee.sop</groupId>
|
||||
|
@@ -29,7 +29,7 @@
|
||||
<dependency>
|
||||
<groupId>com.gitee.sop</groupId>
|
||||
<artifactId>sop-service-common</artifactId>
|
||||
<version>1.5.0-SNAPSHOT</version>
|
||||
<version>1.6.0-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
|
@@ -20,7 +20,7 @@
|
||||
<dependency>
|
||||
<groupId>com.gitee.sop</groupId>
|
||||
<artifactId>sop-service-common</artifactId>
|
||||
<version>1.5.0-SNAPSHOT</version>
|
||||
<version>1.6.0-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<!-- eureka 服务发现 -->
|
||||
<dependency>
|
||||
|
@@ -23,7 +23,7 @@
|
||||
<dependency>
|
||||
<groupId>com.gitee.sop</groupId>
|
||||
<artifactId>sop-service-common</artifactId>
|
||||
<version>1.5.0-SNAPSHOT</version>
|
||||
<version>1.6.0-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.gitee.sop</groupId>
|
||||
|
Reference in New Issue
Block a user