Skip to content

Commit ea383ee

Browse files
committed
⬆️ 使用 justauth-spring-boot-starter 实现第三方登录,同时缓存使用自定义 redis 缓存 state
1 parent 23d65a8 commit ea383ee

File tree

7 files changed

+170
-122
lines changed

7 files changed

+170
-122
lines changed

spring-boot-demo-social/pom.xml

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
2121
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
2222
<java.version>1.8</java.version>
23-
<spring.social.version>1.1.6.RELEASE</spring.social.version>
23+
<justauth-spring-boot.version>1.0.0</justauth-spring-boot.version>
2424
</properties>
2525

2626
<dependencies>
@@ -35,11 +35,22 @@
3535
<scope>test</scope>
3636
</dependency>
3737

38+
<dependency>
39+
<groupId>org.springframework.boot</groupId>
40+
<artifactId>spring-boot-starter-data-redis</artifactId>
41+
</dependency>
42+
43+
<!-- 对象池,使用redis时必须引入 -->
44+
<dependency>
45+
<groupId>org.apache.commons</groupId>
46+
<artifactId>commons-pool2</artifactId>
47+
</dependency>
48+
3849
<!-- oauth工具类 -->
3950
<dependency>
40-
<groupId>me.zhyd.oauth</groupId>
41-
<artifactId>JustAuth</artifactId>
42-
<version>1.9.5</version>
51+
<groupId>com.xkcoding</groupId>
52+
<artifactId>justauth-spring-boot-starter</artifactId>
53+
<version>${justauth-spring-boot.version}</version>
4354
</dependency>
4455

4556
<dependency>

spring-boot-demo-social/src/main/java/com/xkcoding/social/SpringBootDemoSocialApplication.java

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,8 @@
88
* 启动器
99
* </p>
1010
*
11-
* @package: com.xkcoding.social
12-
* @description: 启动器
13-
* @author: yangkai.shen
14-
* @date: Created in 2019-02-19 16:04
15-
* @copyright: Copyright (c) 2019
16-
* @version: V1.0
17-
* @modified: yangkai.shen
11+
* @author yangkai.shen
12+
* @date Created in 2019-08-09 13:51
1813
*/
1914
@SpringBootApplication
2015
public class SpringBootDemoSocialApplication {
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
package com.xkcoding.social.config.justauth;
2+
3+
import me.zhyd.oauth.cache.AuthStateCache;
4+
import org.springframework.context.annotation.Bean;
5+
import org.springframework.context.annotation.Configuration;
6+
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
7+
import org.springframework.data.redis.core.RedisTemplate;
8+
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
9+
import org.springframework.data.redis.serializer.StringRedisSerializer;
10+
11+
import java.io.Serializable;
12+
13+
/**
14+
* <p>
15+
* JustAuth自动装配
16+
* </p>
17+
*
18+
* @author yangkai.shen
19+
* @date Created in 2019-08-09 14:21
20+
*/
21+
@Configuration
22+
public class JustAuthConfig {
23+
/**
24+
* 默认情况下的模板只能支持RedisTemplate<String, String>,也就是只能存入字符串,因此支持序列化
25+
*/
26+
@Bean
27+
public RedisTemplate<String, Serializable> redisCacheTemplate(LettuceConnectionFactory redisConnectionFactory) {
28+
RedisTemplate<String, Serializable> template = new RedisTemplate<>();
29+
template.setKeySerializer(new StringRedisSerializer());
30+
template.setValueSerializer(new GenericJackson2JsonRedisSerializer());
31+
template.setConnectionFactory(redisConnectionFactory);
32+
return template;
33+
}
34+
35+
@Bean
36+
public AuthStateCache authStateCache(RedisTemplate<String, String> redisCacheTemplate) {
37+
return new JustAuthRedisStateCache(redisCacheTemplate);
38+
}
39+
}
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
package com.xkcoding.social.config.justauth;
2+
3+
import lombok.RequiredArgsConstructor;
4+
import me.zhyd.oauth.cache.AuthStateCache;
5+
import org.springframework.data.redis.core.RedisTemplate;
6+
7+
import java.util.concurrent.TimeUnit;
8+
9+
/**
10+
* <p>
11+
* Redis作为JustAuth的State的缓存
12+
* </p>
13+
*
14+
* @author yangkai.shen
15+
* @date Created in 2019-08-09 14:22
16+
*/
17+
@RequiredArgsConstructor
18+
public class JustAuthRedisStateCache implements AuthStateCache {
19+
private final RedisTemplate<String, String> redisTemplate;
20+
private static final long DEF_TIMEOUT = 3 * 60 * 1000;
21+
22+
/**
23+
* 存入缓存
24+
*
25+
* @param key 缓存key
26+
* @param value 缓存内容
27+
*/
28+
@Override
29+
public void cache(String key, String value) {
30+
this.cache(key, value, DEF_TIMEOUT);
31+
}
32+
33+
/**
34+
* 存入缓存
35+
*
36+
* @param key 缓存key
37+
* @param value 缓存内容
38+
* @param timeout 指定缓存过期时间(毫秒)
39+
*/
40+
@Override
41+
public void cache(String key, String value, long timeout) {
42+
redisTemplate.opsForValue().set(key, value, timeout, TimeUnit.MILLISECONDS);
43+
}
44+
45+
/**
46+
* 获取缓存内容
47+
*
48+
* @param key 缓存key
49+
* @return 缓存内容
50+
*/
51+
@Override
52+
public String get(String key) {
53+
return redisTemplate.opsForValue().get(key);
54+
}
55+
56+
/**
57+
* 是否存在key,如果对应key的value值已过期,也返回false
58+
*
59+
* @param key 缓存key
60+
* @return true:存在key,并且value没过期;false:key不存在或者已过期
61+
*/
62+
@Override
63+
public boolean containsKey(String key) {
64+
Long expire = redisTemplate.getExpire(key, TimeUnit.MILLISECONDS);
65+
if (expire == null) {
66+
expire = 0L;
67+
}
68+
return expire > 0;
69+
}
70+
}
Lines changed: 18 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,14 @@
11
package com.xkcoding.social.controller;
22

3-
import cn.hutool.core.lang.Dict;
3+
import cn.hutool.core.util.StrUtil;
44
import cn.hutool.json.JSONUtil;
5-
import com.xkcoding.social.props.OAuthProperties;
5+
import com.xkcoding.justauth.AuthRequestFactory;
66
import lombok.RequiredArgsConstructor;
77
import lombok.extern.slf4j.Slf4j;
8-
import me.zhyd.oauth.config.AuthConfig;
98
import me.zhyd.oauth.config.AuthSource;
109
import me.zhyd.oauth.model.AuthCallback;
1110
import me.zhyd.oauth.model.AuthResponse;
12-
import me.zhyd.oauth.request.*;
11+
import me.zhyd.oauth.request.AuthRequest;
1312
import me.zhyd.oauth.utils.AuthStateUtils;
1413
import org.springframework.beans.factory.annotation.Autowired;
1514
import org.springframework.web.bind.annotation.GetMapping;
@@ -19,6 +18,9 @@
1918

2019
import javax.servlet.http.HttpServletResponse;
2120
import java.io.IOException;
21+
import java.util.List;
22+
import java.util.Map;
23+
import java.util.stream.Collectors;
2224

2325
/**
2426
* <p>
@@ -38,14 +40,15 @@
3840
@RequestMapping("/oauth")
3941
@RequiredArgsConstructor(onConstructor_ = @Autowired)
4042
public class OauthController {
41-
private final OAuthProperties properties;
43+
private final AuthRequestFactory factory;
4244

4345
/**
4446
* 登录类型
4547
*/
4648
@GetMapping
47-
public Dict loginType() {
48-
return Dict.create().set("QQ登录", "http://oauth.xkcoding.com/demo/oauth/login/qq").set("GitHub登录", "http://oauth.xkcoding.com/demo/oauth/login/github").set("微信登录", "http://oauth.xkcoding.com/demo/oauth/login/wechat").set("Google登录", "http://oauth.xkcoding.com/demo/oauth/login/google").set("Microsoft 登录", "http://oauth.xkcoding.com/demo/oauth/login/microsoft").set("小米登录", "http://oauth.xkcoding.com/demo/oauth/login/mi");
49+
public Map<String, String> loginType() {
50+
List<String> oauthList = factory.oauthList();
51+
return oauthList.stream().collect(Collectors.toMap(oauth -> oauth.toLowerCase() + "登录", oauth -> "http://oauth.xkcoding.com/demo/oauth/login/" + oauth.toLowerCase()));
4952
}
5053

5154
/**
@@ -57,8 +60,8 @@ public Dict loginType() {
5760
*/
5861
@RequestMapping("/login/{oauthType}")
5962
public void renderAuth(@PathVariable String oauthType, HttpServletResponse response) throws IOException {
60-
AuthRequest authRequest = getAuthRequest(oauthType);
61-
response.sendRedirect(authRequest.authorize(AuthStateUtils.createState()));
63+
AuthRequest authRequest = factory.get(getAuthSource(oauthType));
64+
response.sendRedirect(authRequest.authorize(oauthType + "::" + AuthStateUtils.createState()));
6265
}
6366

6467
/**
@@ -70,59 +73,17 @@ public void renderAuth(@PathVariable String oauthType, HttpServletResponse respo
7073
*/
7174
@RequestMapping("/{oauthType}/callback")
7275
public AuthResponse login(@PathVariable String oauthType, AuthCallback callback) {
73-
AuthRequest authRequest = getAuthRequest(oauthType);
76+
AuthRequest authRequest = factory.get(getAuthSource(oauthType));
7477
AuthResponse response = authRequest.login(callback);
7578
log.info("【response】= {}", JSONUtil.toJsonStr(response));
7679
return response;
7780
}
7881

79-
private AuthRequest getAuthRequest(String oauthType) {
80-
AuthSource authSource = AuthSource.valueOf(oauthType.toUpperCase());
81-
switch (authSource) {
82-
case QQ:
83-
return getQqAuthRequest();
84-
case GITHUB:
85-
return getGithubAuthRequest();
86-
case WECHAT:
87-
return getWechatAuthRequest();
88-
case GOOGLE:
89-
return getGoogleAuthRequest();
90-
case MICROSOFT:
91-
return getMicrosoftAuthRequest();
92-
case MI:
93-
return getMiAuthRequest();
94-
default:
95-
throw new RuntimeException("暂不支持的第三方登录");
82+
private AuthSource getAuthSource(String type) {
83+
if (StrUtil.isNotBlank(type)) {
84+
return AuthSource.valueOf(type.toUpperCase());
85+
} else {
86+
throw new RuntimeException("不支持的类型");
9687
}
9788
}
98-
99-
private AuthRequest getQqAuthRequest() {
100-
AuthConfig authConfig = properties.getQq();
101-
return new AuthQqRequest(authConfig);
102-
}
103-
104-
private AuthRequest getGithubAuthRequest() {
105-
AuthConfig authConfig = properties.getGithub();
106-
return new AuthGithubRequest(authConfig);
107-
}
108-
109-
private AuthRequest getWechatAuthRequest() {
110-
AuthConfig authConfig = properties.getWechat();
111-
return new AuthWeChatRequest(authConfig);
112-
}
113-
114-
private AuthRequest getGoogleAuthRequest() {
115-
AuthConfig authConfig = properties.getGoogle();
116-
return new AuthGoogleRequest(authConfig);
117-
}
118-
119-
private AuthRequest getMicrosoftAuthRequest() {
120-
AuthConfig authConfig = properties.getMicrosoft();
121-
return new AuthMicrosoftRequest(authConfig);
122-
}
123-
124-
private AuthRequest getMiAuthRequest() {
125-
AuthConfig authConfig = properties.getMi();
126-
return new AuthMiRequest(authConfig);
127-
}
12889
}

spring-boot-demo-social/src/main/java/com/xkcoding/social/props/OAuthProperties.java

Lines changed: 0 additions & 54 deletions
This file was deleted.

spring-boot-demo-social/src/main/resources/application.yml

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,27 @@ server:
33
servlet:
44
context-path: /demo
55

6+
spring:
7+
redis:
8+
host: localhost
9+
# 连接超时时间(记得添加单位,Duration)
10+
timeout: 10000ms
11+
# Redis默认情况下有16个分片,这里配置具体使用的分片
12+
# database: 0
13+
lettuce:
14+
pool:
15+
# 连接池最大连接数(使用负值表示没有限制) 默认 8
16+
max-active: 8
17+
# 连接池最大阻塞等待时间(使用负值表示没有限制) 默认 -1
18+
max-wait: -1ms
19+
# 连接池中的最大空闲连接 默认 8
20+
max-idle: 8
21+
# 连接池中的最小空闲连接 默认 0
22+
min-idle: 0
23+
cache:
24+
# 一般来说是不用配置的,Spring Cache 会根据依赖的包自行装配
25+
type: redis
26+
627
oauth:
728
qq:
829
client-id: 1015*****
@@ -28,3 +49,8 @@ oauth:
2849
client-id: 2882303**************
2950
client-secret: nFeTt89Yn**************
3051
redirect-uri: http://oauth.xkcoding.com/demo/oauth/mi/callback
52+
wechat_enterprise:
53+
client-id: ww58**********6fbc
54+
client-secret: 8G6PCr0****************************yzaPc78
55+
redirect-uri: http://oauth.xkcoding.com/demo/oauth/wechat_enterprise/callback
56+
agent-id: 10*******02

0 commit comments

Comments
 (0)