接着上一篇博客: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的單點登陸整合完畢,單次登陸,處處登陸;單次退出,處處退出。