接着上一篇博客:https://www.cnblogs.com/wwjj4811/p/14505886.html
概述
单点登录SSO(Single Sign On)说得简单点就是在一个多系统共存的环境下,用户在一处登录后,就不用在其他系统中登录,也就是用户的一次登录能得到其他所有系统的信任。单点登录在大型网站里使用得非常频繁,例如像阿里巴巴这样的网站,在网站的背后是成百上千的子系统,用户一次操作或交易可能涉及到几十个子系统的协作,如果每个子系统都需要用户认证,不仅用户会疯掉,各子系统也会为这种重复认证授权的逻辑搞疯掉
准备工作
sql
向oauth_client_detials表添加两条数据
INSERT INTO `study-security`.`oauth_client_details`(`client_id`, `resource_ids`, `client_secret`, `scope`, `authorized_grant_types`, `web_server_redirect_uri`, `authorities`, `access_token_validity`, `refresh_token_validity`, `additional_information`, `autoapprove`) VALUES ('client1', NULL, '$2a$10$fTo73KCRzU3HXcPGtaTmxu9zDIrnoud6GvhlKF0sIxWzm7awSkGOK', 'MEMBER_READ,MEMBER_WRITE', 'authorization_code,refresh_code', 'http://localhost:9001/login', NULL, 50000, NULL, NULL, 'true');
INSERT INTO `study-security`.`oauth_client_details`(`client_id`, `resource_ids`, `client_secret`, `scope`, `authorized_grant_types`, `web_server_redirect_uri`, `authorities`, `access_token_validity`, `refresh_token_validity`, `additional_information`, `autoapprove`) VALUES ('client2', NULL, '$2a$10$fTo73KCRzU3HXcPGtaTmxu9zDIrnoud6GvhlKF0sIxWzm7awSkGOK', 'MEMBER_READ', 'authorization_code,refresh_code', 'http://localhost:9002/login', NULL, 50000, NULL, NULL, 'true');
SSO 会员客户端1
创建cloud-oauth2-sso-client1模块,pom.xml如下:
<dependencies>
<dependency>
<groupId>com.wj</groupId>
<artifactId>cloud-oauth2-base</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-oauth2</artifactId>
</dependency>
<!-- 注册到 Eureka
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-springsecurity5</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
</dependency>
</dependencies>
application.yml
server:
port: 9001
spring:
thymeleaf:
cache: false
security:
oauth2:
client:
client-id: client1 # 当前客户端id
client-secret: wj-secret # 客户端的密码
user-authorization-uri: http://localhost:8090/auth/oauth/authorize #请求认证的地址,获取授权码地址
access-token-uri: http://localhost:8090/auth/oauth/token # 请求令牌的地址
resource:
jwt:
# 当用户授权之后会响应一个授权码,重定向到当前应用的 http://localhost:9001/login?code=xxx
# 自动的会对 /login 去获取令牌,获取到令牌后会通过 key-uri 获取到的公钥进行解密然后本地身份认证和授权(Session)
key-uri: http://localhost:8090/auth/oauth/token_key # 获取公钥
主启动类和控制器
@SpringBootApplication
public class SsoClient1Application {
public static void main(String[] args) {
SpringApplication.run(SsoClient1Application.class, args);
}
}
@Controller
public class MainController {
@GetMapping("/")
public String index(){
return "index";
}
@GetMapping("/member")
public String member(){
return "member";
}
}
创建前端html,两个页面都放到templates下面
index.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.w3.org/1999/xhtml">
<head>
<meta charset="UTF-8">
<title>sso1 首页</title>
</head>
<body>
<h1>
<a th:href="@{/member}">客户端1-查看会员</a>
</h1>
</body>
</html>
member.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.w3.org/1999/xhtml">
<head>
<meta charset="UTF-8">
<title>首页</title>
</head>
<body>
<div>
<h1>客户端1,欢迎您![[${#authentication.name}]]</h1>
<h3><a th:href="@{/logout}">退出系统</a></h3>
</div>
</body>
</html>
sso登陆配置类:
@Configuration
@EnableOAuth2Sso
public class SsoSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
//首页所有人可以访问
.antMatchers("/").permitAll()
.anyRequest().authenticated();
}
}
SSO 会员客户端2
创建模块cloud-oauth2-sso-client2
cloud-oauth2-sso-client2和cloud-oauth2-sso-client1基本一样,端口号从9001改成9002,所有client1改成client2
单点登陆测试
先启动认证服务器,再启动sso客户端,否则会直接报错。因为客户端启动时会去发送请求获取公钥。
先进入http://localhost:9001/,点击
因为没有登陆,所以直接跳转到登录页面,这里的登录页是认证服务器的,账号密码是 admin/1234
登陆成功后,跳转到member页面
这时候我们直接访问:http://localhost:9002/member,发现直接访问成功,不需要登陆,sso单点登录整合成功
SSO 退出系统
在单点登陆系统中,我们希望退出登陆当前系统后,将所有客户端都退出,我们修改配置SsoSecurityConfig:
@Configuration
@EnableOAuth2Sso
public class SsoSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
//首页所有人可以访问
.antMatchers("/").permitAll()
.anyRequest().authenticated()
.and()
//当前应用退出
.logout()
//退出成功后,跳转到认证服务器退出
.logoutSuccessUrl("http://localhost:8090/auth/logout")
.and().csrf().disable();
}
}
测试:
我们先在sso1客户端中退出,点击退出系统
再点击logout out
然后就跳转到认证服务器的登陆页面了
这时候我们再刷新sso2客户端的页面,就发现需要重新登陆了
至此,Spring Security OAuth2的单点登陆整合完毕,单次登陆,处处登陆;单次退出,处处退出。