+ * 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。 + *+ * + * @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); +} diff --git a/sop-example/sop-auth/src/main/java/com/gitee/sop/sopauth/auth/OpenUser.java b/sop-example/sop-auth/src/main/java/com/gitee/sop/sopauth/auth/OpenUser.java new file mode 100644 index 00000000..5e7338b3 --- /dev/null +++ b/sop-example/sop-auth/src/main/java/com/gitee/sop/sopauth/auth/OpenUser.java @@ -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(); +} diff --git a/sop-example/sop-auth/src/main/java/com/gitee/sop/sopauth/auth/RefreshToken.java b/sop-example/sop-auth/src/main/java/com/gitee/sop/sopauth/auth/RefreshToken.java new file mode 100644 index 00000000..acd04d54 --- /dev/null +++ b/sop-example/sop-auth/src/main/java/com/gitee/sop/sopauth/auth/RefreshToken.java @@ -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; + } + +} diff --git a/sop-example/sop-auth/src/main/java/com/gitee/sop/sopauth/auth/TokenPair.java b/sop-example/sop-auth/src/main/java/com/gitee/sop/sopauth/auth/TokenPair.java new file mode 100644 index 00000000..07e11214 --- /dev/null +++ b/sop-example/sop-auth/src/main/java/com/gitee/sop/sopauth/auth/TokenPair.java @@ -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; + } + +} diff --git a/sop-example/sop-auth/src/main/java/com/gitee/sop/sopauth/auth/exception/LoginErrorException.java b/sop-example/sop-auth/src/main/java/com/gitee/sop/sopauth/auth/exception/LoginErrorException.java new file mode 100644 index 00000000..92e61d6a --- /dev/null +++ b/sop-example/sop-auth/src/main/java/com/gitee/sop/sopauth/auth/exception/LoginErrorException.java @@ -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); + } + +} \ No newline at end of file diff --git a/sop-example/sop-auth/src/main/java/com/gitee/sop/sopauth/auth/impl/AppIdManagerImpl.java b/sop-example/sop-auth/src/main/java/com/gitee/sop/sopauth/auth/impl/AppIdManagerImpl.java new file mode 100644 index 00000000..9c49954b --- /dev/null +++ b/sop-example/sop-auth/src/main/java/com/gitee/sop/sopauth/auth/impl/AppIdManagerImpl.java @@ -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; + } +} diff --git a/sop-example/sop-auth/src/main/java/com/gitee/sop/sopauth/auth/impl/OAuth2ManagerCache.java b/sop-example/sop-auth/src/main/java/com/gitee/sop/sopauth/auth/impl/OAuth2ManagerCache.java new file mode 100644 index 00000000..102ed522 --- /dev/null +++ b/sop-example/sop-auth/src/main/java/com/gitee/sop/sopauth/auth/impl/OAuth2ManagerCache.java @@ -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