用超级少的代码来实现单点登陆和社交登陆。
目录
- 第一步,改一下本地 host
- 第二步,构建单点服务端(SsoServer)
- 第三步,构建单点客户端(Servlet - Spring Boot)
- 第四步,构建单点客户端(WebFlux - Spring Gateway)
- 扩展: 集成社交登陆(GitHub)
- 项目源码
第一步,改一下本地 host
这边交代一下,我们的 host 配置
1 | 127.0.0.1 example.hocgin.local |
第二步,构建单点服务机(SsoServer)
- 引入基础依赖
1
2
3
4
5
6
7
8
9
10
11
12
13
14<xml>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-oauth2-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-oauth2</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</xml> - 在 Spring Security 进行配置
2.1 配置 Web Security这个主要是对登陆的方式和URI进行配置,如果使用默认的话只要开启 OAuth2.0 的配置即可。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37/**
* Created by hocgin on 2020/1/6.
* email: [email protected]
*
* @author hocgin
*/
public class WebSecurityConfigurer extends WebSecurityConfigurerAdapter {
private final AuthenticationConfigs authenticationConfigs;
private final UserDetailsService userDetailsService;
protected void configure(HttpSecurity http) throws Exception {
// 基础信息配置
http.csrf().disable()
.cors().disable()
.authorizeRequests()
// 使用 GitHub 进行社交登陆
.antMatchers("/login/oauth2/code/github").permitAll()
.anyRequest().authenticated().and()
;
// 异常处理配置(这边针对AJAX进行不同处理,如果不需要可以忽略)
http.exceptionHandling()
.defaultAuthenticationEntryPointFor(new AjaxAuthenticationEntryPoint(), new IsAjaxRequestMatcher())
.defaultAccessDeniedHandlerFor(new AjaxAccessDeniedHandler(), new IsAjaxRequestMatcher());
// 登陆相关配置
authenticationConfigs.configure(http, authenticationManagerBean());
}
// 这边省略了大量非重代码..
}2.2 资源服务配置1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class AuthenticationConfigs {
static final String LOGIN_SUCCESS_PAGE = "/index";
static final String LOGIN_PAGE = "/login";
public void configure(HttpSecurity http, AuthenticationManager authenticationManager) throws Exception {
final AuthorizedSuccessHandle successHandler = new AuthorizedSuccessHandle(LOGIN_SUCCESS_PAGE);
final AuthorizedFailureHandle failureHandle = new AuthorizedFailureHandle(LOGIN_PAGE);
// ==== OAuth2.0 ====
http.oauth2Client();
http.oauth2Login().loginPage(LOGIN_PAGE);
// ==== Form 表单 ====
{
http.formLogin().loginPage(LOGIN_PAGE)
.successHandler(successHandler)
.failureHandler(failureHandle)
.permitAll();
}
}
}主要是配置资源的访问权限,可以理解为配置单点客户机的用户名和密码
2.3 配置允许的单点客户端账户1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
private final AuthenticationManager authenticationManager;
private final PasswordEncoder passwordEncoder;
private final SsoProperties properties;
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
// 这边使用内存的方式来存储,单点客户端信息
InMemoryClientDetailsServiceBuilder builder = clients.inMemory();
for (SsoProperties.Client client : properties.getClients()) {
builder.withClient(client.getClientId())
.secret(passwordEncoder.encode(client.getClientSecret()))
.authorizedGrantTypes("client_credentials", "authorization_code", "refresh_token", "password")
.scopes("user_info")
.redirectUris(client.getRedirectUris())
.autoApprove(true);
}
}
public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception {
oauthServer.allowFormAuthenticationForClients()
.tokenKeyAccess("permitAll()")
.checkTokenAccess("isAuthenticated()")
;
}
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints.authenticationManager(authenticationManager);
}
}1
2
3
4
5
6
7
8
9
10server:
port: 20000
sso:
oauth:
clients:
- client-id: client_example
client-secret: hocgin
redirect-uris:
- http://example.hocgin.local:20001/login/oauth2/code/custom
- http://example2.hocgin.local:20002/login/oauth2/code/custom
⚠️ 注意哦,这边只是说明了单点服务端的一些重点配置,如果需要完整的配置可以参考文章末尾的源码哈。当然这边已经是最最复杂的部分了。如果你已经看到这边了,恭喜你!后面啥代码都不用写啦。
第三步,构建单点客户机(Servlet) - Spring Boot
- 引入依赖
1
2
3
4
5<dependency>
<groupId>in.hocg.boot</groupId>
<artifactId>sso-client-spring-boot-starter</artifactId>
<version>1.0.0-SNAPSHOT</version>
</dependency> - 进行项目配置
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24server:
port: 20002
spring:
security:
oauth2:
shostname: http://sso.hocgin.local:20000
client:
registration:
custom:
client-id: client_example
client-secret: hocgin
redirect-uri: '{baseUrl}/{action}/oauth2/code/{registrationId}'
authorization-grant-type: authorization_code
provider:
custom:
user-info-uri: ${spring.security.oauth2.shostname}/oauth/user
authorization-uri: ${spring.security.oauth2.shostname}/oauth/authorize
token-uri: ${spring.security.oauth2.shostname}/oauth/token
user-name-attribute: name
boot:
sso:
client:
ignore-urls:
- '/ignore'
第四步,构建单点客户机(WebFlux) - Spring Gateway
- 引入依赖
1
2
3
4
5<dependency>
<groupId>in.hocg.boot</groupId>
<artifactId>sso-client-spring-boot-starter</artifactId>
<version>1.0.0-SNAPSHOT</version>
</dependency> - 进行项目配置嘿嘿,其实第三步和第四步是完完全全一样的啦!已经在 Servlet 和 Webflux 上做兼容了啦。当然以上的代码完全适用于任何 Spring Boot 项目,例如: Spring Boot Admin。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23spring:
security:
oauth2:
shostname: http://sso.hocgin.local:20000
client:
registration:
custom:
client-id: client_example
client-secret: hocgin
redirect-uri: '{baseUrl}/{action}/oauth2/code/{registrationId}'
authorization-grant-type: authorization_code
provider:
custom:
user-info-uri: ${spring.security.oauth2.shostname}/oauth/user
authorization-uri: ${spring.security.oauth2.shostname}/oauth/authorize
token-uri: ${spring.security.oauth2.shostname}/oauth/token
user-name-attribute: name
boot:
sso:
client:
ignore-urls:
- '/ignore'
扩展: 集成社交登陆(GitHub)
如果我们需要集成一些标准的 OAuth2.0 只需要在 SSO-Server 上做集成就可以了。以下配置可以配置在 SSO-Server 上。
- 配置yml文件
1
2
3
4
5
6
7
8
9
10spring:
security:
oauth2:
client:
registration:
github:
client-id: (填写你自己的)
client-secret: (填写你自己的)
client-name: Github Login
redirect-uri: '{baseUrl}/{action}/oauth2/code/{registrationId}' - 在html代码里面使用OK! 你已经简单的集成了GitHub的社交登陆了。没办法在水一篇了很遗憾..
1
2
3
4<form th:action="@{/oauth2/authorization/github}" method="GET">
<input type="hidden" name="scope" value="read_stream,user_posts,user_photos"/>
<button type="submit">github</button>
</form>
运行演示
流程:
- 访问 example2.hocgin.local:20002/user
- 登陆后跳转 example2.hocgin.local:20002/user
- 查看 example.hocgin.local:20001/user 登陆信息
- 查看 sso.hocgin.local:20000/user 登陆信息