diff --git a/src/main/java/me/zhyd/oauth/config/AuthSource.java b/src/main/java/me/zhyd/oauth/config/AuthSource.java index 33268476e864fd794534ceaeb68ae08599a2df13..fb6cad25e6f3c8f2d085f24e2512df31b10b017e 100644 --- a/src/main/java/me/zhyd/oauth/config/AuthSource.java +++ b/src/main/java/me/zhyd/oauth/config/AuthSource.java @@ -420,6 +420,30 @@ public enum AuthSource { public String userInfo() { return "https://open.snssdk.com/data/user_profile"; } + }, + /** + * Teambition + */ + TEAMBITION { + @Override + public String authorize() { + return "https://account.teambition.com/oauth2/authorize"; + } + + @Override + public String accessToken() { + return "https://account.teambition.com/oauth2/access_token"; + } + + @Override + public String refresh() { + return "https://account.teambition.com/oauth2/refresh_token"; + } + + @Override + public String userInfo() { + return "https://account.teambition.com/users/me"; + } }; /** diff --git a/src/main/java/me/zhyd/oauth/request/AuthWeiboRequest.java b/src/main/java/me/zhyd/oauth/request/AuthWeiboRequest.java index 366ee2234f9da7a57d4b5f0f8bb5c3ce4741cbb8..5129df0afd556271387b2020852854f15d6f9c03 100644 --- a/src/main/java/me/zhyd/oauth/request/AuthWeiboRequest.java +++ b/src/main/java/me/zhyd/oauth/request/AuthWeiboRequest.java @@ -10,9 +10,12 @@ import me.zhyd.oauth.model.AuthCallback; import me.zhyd.oauth.model.AuthToken; import me.zhyd.oauth.model.AuthUser; import me.zhyd.oauth.model.AuthUserGender; +import me.zhyd.oauth.url.WeiboUrlBuilder; +import me.zhyd.oauth.url.entity.AuthAccessTokenEntity; +import me.zhyd.oauth.url.entity.AuthAuthorizeEntity; +import me.zhyd.oauth.url.entity.AuthUserInfoEntity; import me.zhyd.oauth.utils.IpUtils; import me.zhyd.oauth.utils.StringUtils; -import me.zhyd.oauth.utils.UrlBuilder; /** @@ -25,13 +28,15 @@ import me.zhyd.oauth.utils.UrlBuilder; public class AuthWeiboRequest extends BaseAuthRequest { public AuthWeiboRequest(AuthConfig config) { - super(config, AuthSource.WEIBO); + super(config, AuthSource.WEIBO, new WeiboUrlBuilder()); } @Override protected AuthToken getAccessToken(AuthCallback authCallback) { - String accessTokenUrl = UrlBuilder.getWeiboAccessTokenUrl(config.getClientId(), config.getClientSecret(), authCallback.getCode(), config - .getRedirectUri()); + String accessTokenUrl = this.urlBuilder.getAccessTokenUrl(AuthAccessTokenEntity.builder() + .config(config) + .code(authCallback.getCode()) + .build()); HttpResponse response = HttpRequest.post(accessTokenUrl).execute(); String accessTokenStr = response.body(); JSONObject accessTokenObject = JSONObject.parseObject(accessTokenStr); @@ -51,7 +56,9 @@ public class AuthWeiboRequest extends BaseAuthRequest { String accessToken = authToken.getAccessToken(); String uid = authToken.getUid(); String oauthParam = String.format("uid=%s&access_token=%s", uid, accessToken); - HttpResponse response = HttpRequest.get(UrlBuilder.getWeiboUserInfoUrl(oauthParam)) + HttpResponse response = HttpRequest.get(this.urlBuilder.getUserInfoUrl(AuthUserInfoEntity.builder() + .extra(oauthParam) + .build())) .header("Authorization", "OAuth2 " + oauthParam) .header("API-RemoteIP", IpUtils.getIp()) .execute(); @@ -82,6 +89,8 @@ public class AuthWeiboRequest extends BaseAuthRequest { */ @Override public String authorize() { - return UrlBuilder.getWeiboAuthorizeUrl(config.getClientId(), config.getRedirectUri(), config.getState()); + return this.urlBuilder.getAuthorizeUrl(AuthAuthorizeEntity.builder() + .config(config) + .build()); } } diff --git a/src/main/java/me/zhyd/oauth/request/BaseAuthRequest.java b/src/main/java/me/zhyd/oauth/request/BaseAuthRequest.java index 8cf1fb186423898617e3c7e0090df47e82c64360..4dde76e84e46a6ac51c6cdd61eab10a3e01c63fc 100644 --- a/src/main/java/me/zhyd/oauth/request/BaseAuthRequest.java +++ b/src/main/java/me/zhyd/oauth/request/BaseAuthRequest.java @@ -8,6 +8,7 @@ import me.zhyd.oauth.model.AuthCallback; import me.zhyd.oauth.model.AuthResponse; import me.zhyd.oauth.model.AuthToken; import me.zhyd.oauth.model.AuthUser; +import me.zhyd.oauth.url.AbstractUrlBuilder; import me.zhyd.oauth.utils.AuthChecker; /** @@ -19,6 +20,7 @@ import me.zhyd.oauth.utils.AuthChecker; public abstract class BaseAuthRequest implements AuthRequest { protected AuthConfig config; protected AuthSource source; + protected AbstractUrlBuilder urlBuilder; public BaseAuthRequest(AuthConfig config, AuthSource source) { this.config = config; @@ -30,6 +32,11 @@ public abstract class BaseAuthRequest implements AuthRequest { AuthChecker.checkConfig(config, source); } + public BaseAuthRequest(AuthConfig config, AuthSource source, AbstractUrlBuilder urlBuilder) { + this(config, source); + this.urlBuilder = urlBuilder; + } + protected abstract AuthToken getAccessToken(AuthCallback authCallback); protected abstract AuthUser getUserInfo(AuthToken authToken); diff --git a/src/main/java/me/zhyd/oauth/url/AbstractUrlBuilder.java b/src/main/java/me/zhyd/oauth/url/AbstractUrlBuilder.java new file mode 100644 index 0000000000000000000000000000000000000000..88350b3cf9964ba30fc81c46099e8e1d1d95d7d2 --- /dev/null +++ b/src/main/java/me/zhyd/oauth/url/AbstractUrlBuilder.java @@ -0,0 +1,56 @@ +package me.zhyd.oauth.url; + +import me.zhyd.oauth.url.entity.*; +import me.zhyd.oauth.utils.StringUtils; + +/** + * @author yadong.zhang (yadong.zhang0415(a)gmail.com) + * @version 1.0 + * @since 1.8 + */ +public abstract class AbstractUrlBuilder { + + /** + * 获取AccessToken的URL + * + * @return AccessTokenUrl + */ + public abstract String getAccessTokenUrl(AuthAccessTokenEntity accessTokenEntity); + + /** + * 获取用户信息的URL + * + * @return UserInfoUrl + */ + public abstract String getUserInfoUrl(AuthUserInfoEntity userInfoEntity); + + /** + * 获取跳转授权页面的URL + * + * @return AuthorizeUrl + */ + public abstract String getAuthorizeUrl(AuthAuthorizeEntity authorizeEntity); + + /** + * 获取刷新token的URL + * + * @return RefreshUrl + */ + public abstract String getRefreshUrl(AuthRefreshTokenEntity refreshTokenEntity); + + /** + * 获取取消授权的URL + * + * @return RevokeUrl + */ + public abstract String getRevokeUrl(AuthRevokeEntity revokeEntity); + + /** + * 获取state,如果为空, 则默认去当前日期的时间戳 + * + * @param state state + */ + protected String getRealState(String state) { + return StringUtils.isEmpty(state) ? String.valueOf(System.currentTimeMillis()) : state; + } +} diff --git a/src/main/java/me/zhyd/oauth/url/WeiboUrlBuilder.java b/src/main/java/me/zhyd/oauth/url/WeiboUrlBuilder.java new file mode 100644 index 0000000000000000000000000000000000000000..ddb8a6cb266392439b6ff30249a3500745e7c591 --- /dev/null +++ b/src/main/java/me/zhyd/oauth/url/WeiboUrlBuilder.java @@ -0,0 +1,48 @@ +package me.zhyd.oauth.url; + +import me.zhyd.oauth.config.AuthConfig; +import me.zhyd.oauth.config.AuthSource; +import me.zhyd.oauth.url.entity.*; + +import java.text.MessageFormat; + +/** + * @author yadong.zhang (yadong.zhang0415(a)gmail.com) + * @version 1.0 + * @since 1.8 + */ +public class WeiboUrlBuilder extends AbstractUrlBuilder { + + private static final String WEIBO_ACCESS_TOKEN_PATTERN = "{0}?client_id={1}&client_secret={2}&grant_type=authorization_code&code={3}&redirect_uri={4}"; + private static final String WEIBO_USER_INFO_PATTERN = "{0}?{1}"; + private static final String WEIBO_AUTHORIZE_PATTERN = "{0}?client_id={1}&response_type=code&redirect_uri={2}&state={3}"; + + @Override + public String getAccessTokenUrl(AuthAccessTokenEntity accessTokenEntity) { + AuthConfig config = accessTokenEntity.getConfig(); + return MessageFormat.format(WEIBO_ACCESS_TOKEN_PATTERN, AuthSource.WEIBO.accessToken(), config.getClientId(), + config.getClientSecret(), accessTokenEntity.getCode(), config.getRedirectUri()); + } + + @Override + public String getUserInfoUrl(AuthUserInfoEntity userInfoEntity) { + return MessageFormat.format(WEIBO_USER_INFO_PATTERN, AuthSource.WEIBO.userInfo(), userInfoEntity.getExtra()); + } + + @Override + public String getAuthorizeUrl(AuthAuthorizeEntity authorizeEntity) { + AuthConfig config = authorizeEntity.getConfig(); + return MessageFormat.format(WEIBO_AUTHORIZE_PATTERN, AuthSource.WEIBO.authorize(), config.getClientId(), + config.getRedirectUri(), this.getRealState(config.getState())); + } + + @Override + public String getRefreshUrl(AuthRefreshTokenEntity refreshTokenEntity) { + return null; + } + + @Override + public String getRevokeUrl(AuthRevokeEntity revokeEntity) { + return null; + } +} diff --git a/src/main/java/me/zhyd/oauth/url/entity/AuthAccessTokenEntity.java b/src/main/java/me/zhyd/oauth/url/entity/AuthAccessTokenEntity.java new file mode 100644 index 0000000000000000000000000000000000000000..d71dbb8b30333e53fc3b8f834a97885f5880516b --- /dev/null +++ b/src/main/java/me/zhyd/oauth/url/entity/AuthAccessTokenEntity.java @@ -0,0 +1,25 @@ +package me.zhyd.oauth.url.entity; + +import lombok.Builder; +import lombok.Getter; +import me.zhyd.oauth.config.AuthConfig; + +/** + * @author yadong.zhang (yadong.zhang0415(a)gmail.com) + * @version 1.0 + * @since 1.8 + */ +@Getter +@Builder +public class AuthAccessTokenEntity { + + /** + * JustAuth的配置类 + */ + private AuthConfig config; + + /** + * 访问AuthorizeUrl后回调时带的参数code + */ + private String code; +} diff --git a/src/main/java/me/zhyd/oauth/url/entity/AuthAuthorizeEntity.java b/src/main/java/me/zhyd/oauth/url/entity/AuthAuthorizeEntity.java new file mode 100644 index 0000000000000000000000000000000000000000..0ae8b31e80e859cc6ee674c9f3d8db19a779117b --- /dev/null +++ b/src/main/java/me/zhyd/oauth/url/entity/AuthAuthorizeEntity.java @@ -0,0 +1,20 @@ +package me.zhyd.oauth.url.entity; + +import lombok.Builder; +import lombok.Getter; +import me.zhyd.oauth.config.AuthConfig; + +/** + * @author yadong.zhang (yadong.zhang0415(a)gmail.com) + * @version 1.0 + * @since 1.8 + */ +@Getter +@Builder +public class AuthAuthorizeEntity { + + /** + * JustAuth的配置类 + */ + private AuthConfig config; +} diff --git a/src/main/java/me/zhyd/oauth/url/entity/AuthRefreshTokenEntity.java b/src/main/java/me/zhyd/oauth/url/entity/AuthRefreshTokenEntity.java new file mode 100644 index 0000000000000000000000000000000000000000..19d07a04aee3d993a51b5880df075c1518fb54e4 --- /dev/null +++ b/src/main/java/me/zhyd/oauth/url/entity/AuthRefreshTokenEntity.java @@ -0,0 +1,14 @@ +package me.zhyd.oauth.url.entity; + +import lombok.Builder; +import lombok.Getter; + +/** + * @author yadong.zhang (yadong.zhang0415(a)gmail.com) + * @version 1.0 + * @since 1.8 + */ +@Getter +@Builder +public class AuthRefreshTokenEntity { +} diff --git a/src/main/java/me/zhyd/oauth/url/entity/AuthRevokeEntity.java b/src/main/java/me/zhyd/oauth/url/entity/AuthRevokeEntity.java new file mode 100644 index 0000000000000000000000000000000000000000..d9ab0a0110fe495d3492ca295409d24ca8c52c1c --- /dev/null +++ b/src/main/java/me/zhyd/oauth/url/entity/AuthRevokeEntity.java @@ -0,0 +1,13 @@ +package me.zhyd.oauth.url.entity; + +import lombok.*; + +/** + * @author yadong.zhang (yadong.zhang0415(a)gmail.com) + * @version 1.0 + * @since 1.8 + */ +@Getter +@Builder +public class AuthRevokeEntity { +} diff --git a/src/main/java/me/zhyd/oauth/url/entity/AuthUserInfoEntity.java b/src/main/java/me/zhyd/oauth/url/entity/AuthUserInfoEntity.java new file mode 100644 index 0000000000000000000000000000000000000000..852d2d2e27f3297b0a201c2d9a227a1046eea04b --- /dev/null +++ b/src/main/java/me/zhyd/oauth/url/entity/AuthUserInfoEntity.java @@ -0,0 +1,26 @@ +package me.zhyd.oauth.url.entity; + +import lombok.Builder; +import lombok.Getter; + +/** + * @author yadong.zhang (yadong.zhang0415(a)gmail.com) + * @version 1.0 + * @since 1.8 + */ +@Getter +@Builder +public class AuthUserInfoEntity { + /** + * 授权返回的token + */ + private String accessToken; + /** + * 用户openId + */ + private String openId; + /** + * 额外的属性 + */ + private String extra; +} diff --git a/src/main/java/me/zhyd/oauth/utils/UrlBuilder.java b/src/main/java/me/zhyd/oauth/utils/UrlBuilder.java index 70d8db7036927a939ae01371928401df16643d74..85187c85ce8ff5e40deed558758549b3a8cd433d 100644 --- a/src/main/java/me/zhyd/oauth/utils/UrlBuilder.java +++ b/src/main/java/me/zhyd/oauth/utils/UrlBuilder.java @@ -21,9 +21,6 @@ public class UrlBuilder { private static final String GOOGLE_ACCESS_TOKEN_PATTERN = "{0}?client_id={1}&client_secret={2}&code={3}&redirect_uri={4}&grant_type=authorization_code"; private static final String GOOGLE_USER_INFO_PATTERN = "{0}?id_token={1}"; - private static final String WEIBO_ACCESS_TOKEN_PATTERN = "{0}?client_id={1}&client_secret={2}&grant_type=authorization_code&code={3}&redirect_uri={4}"; - private static final String WEIBO_USER_INFO_PATTERN = "{0}?{1}"; - private static final String WEIBO_AUTHORIZE_PATTERN = "{0}?client_id={1}&response_type=code&redirect_uri={2}&state={3}"; private static final String GITEE_ACCESS_TOKEN_PATTERN = "{0}?client_id={1}&client_secret={2}&grant_type=authorization_code&code={3}&redirect_uri={4}"; private static final String GITEE_USER_INFO_PATTERN = "{0}?access_token={1}"; @@ -140,41 +137,6 @@ public class UrlBuilder { return MessageFormat.format(GITHUB_AUTHORIZE_PATTERN, AuthSource.GITHUB.authorize(), clientId, redirectUrl, getState(state)); } - /** - * 获取weibo token的接口地址 - * - * @param clientId weibo 应用的App Key - * @param clientSecret weibo 应用的App Secret - * @param code weibo 授权前的code,用来换token - * @param redirectUri 待跳转的页面 - * @return full url - */ - public static String getWeiboAccessTokenUrl(String clientId, String clientSecret, String code, String redirectUri) { - return MessageFormat.format(WEIBO_ACCESS_TOKEN_PATTERN, AuthSource.WEIBO.accessToken(), clientId, clientSecret, code, redirectUri); - } - - /** - * 获取weibo用户详情的接口地址 - * - * @param token weibo 应用的token - * @return full url - */ - public static String getWeiboUserInfoUrl(String token) { - return MessageFormat.format(WEIBO_USER_INFO_PATTERN, AuthSource.WEIBO.userInfo(), token); - } - - /** - * 获取weibo授权地址 - * - * @param clientId weibo 应用的Client ID - * @param redirectUrl weibo 应用授权成功后的回调地址 - * @param state 随机字符串,用于保持会话状态,防止CSRF攻击 - * @return full url - */ - public static String getWeiboAuthorizeUrl(String clientId, String redirectUrl, String state) { - return MessageFormat.format(WEIBO_AUTHORIZE_PATTERN, AuthSource.WEIBO.authorize(), clientId, redirectUrl, getState(state)); - } - /** * 获取gitee token的接口地址 * diff --git a/src/test/java/me/zhyd/oauth/utils/AuthStateTest.java b/src/test/java/me/zhyd/oauth/utils/AuthStateTest.java index f49d382109046e8180779d86d1dab4ece3601919..d73489d27078c1881e0961b834a2cd640843106b 100644 --- a/src/test/java/me/zhyd/oauth/utils/AuthStateTest.java +++ b/src/test/java/me/zhyd/oauth/utils/AuthStateTest.java @@ -26,7 +26,7 @@ public class AuthStateTest { * null */ @Test - public void test() { + public void usage() { String source = "github"; System.out.println("\nstep1 生成state: 预期创建一个新的state..."); String state = AuthState.create(source);