日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

OAuth2 实现单点登录 SSO

發布時間:2023/12/3 编程问答 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 OAuth2 实现单点登录 SSO 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

轉載自??OAuth2 實現單點登錄 SSO

1. 前言

技術這東西吧,看別人寫的好像很簡單似的,到自己去寫的時候就各種問題,“一看就會,一做就錯”。網上關于實現SSO的文章一大堆,但是當你真的照著寫的時候就會發現根本不是那么回事兒,簡直讓人抓狂,尤其是對于我這樣的菜鳥。幾經曲折,終于搞定了,決定記錄下來,以便后續查看。先來看一下效果

2. 準備

2.1. 單點登錄

最常見的例子是,我們打開淘寶APP,首頁就會有天貓、聚劃算等服務的鏈接,當你點擊以后就直接跳過去了,并沒有讓你再登錄一次

下面這個圖是我再網上找的,我覺得畫得比較明白:

可惜有點兒不清晰,于是我又畫了個簡版的:

重要的是理解:

  • SSO服務端和SSO客戶端直接是通過授權以后發放Token的形式來訪問受保護的資源

  • 相對于瀏覽器來說,業務系統是服務端,相對于SSO服務端來說,業務系統是客戶端

  • 瀏覽器和業務系統之間通過會話正常訪問

  • 不是每次瀏覽器請求都要去SSO服務端去驗證,只要瀏覽器和它所訪問的服務端的會話有效它就可以正常訪問

2.2. OAuth2

推薦以下幾篇博客

《OAuth 2.0》

《Spring Security對OAuth2的支持》

3. 利用OAuth2實現單點登錄

接下來,只講跟本例相關的一些配置,不講原理,不講為什么

眾所周知,在OAuth2在有授權服務器、資源服務器、客戶端這樣幾個角色,當我們用它來實現SSO的時候是不需要資源服務器這個角色的,有授權服務器和客戶端就夠了。

授權服務器當然是用來做認證的,客戶端就是各個應用系統,我們只需要登錄成功后拿到用戶信息以及用戶所擁有的權限即可

之前我一直認為把那些需要權限控制的資源放到資源服務器里保護起來就可以實現權限控制,其實是我想錯了,權限控制還得通過Spring Security或者自定義攔截器來做

3.1. Spring Security 、OAuth2、JWT、SSO

在本例中,一定要分清楚這幾個的作用

首先,SSO是一種思想,或者說是一種解決方案,是抽象的,我們要做的就是按照它的這種思想去實現它

其次,OAuth2是用來允許用戶授權第三方應用訪問他在另一個服務器上的資源的一種協議,它不是用來做單點登錄的,但我們可以利用它來實現單點登錄。在本例實現SSO的過程中,受保護的資源就是用戶的信息(包括,用戶的基本信息,以及用戶所具有的權限),而我們想要訪問這這一資源就需要用戶登錄并授權,OAuth2服務端負責令牌的發放等操作,這令牌的生成我們采用JWT,也就是說JWT是用來承載用戶的Access_Token的

最后,Spring Security是用于安全訪問的,這里我們我們用來做訪問權限控制

4. 認證服務器配置

4.1. Maven依賴

<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.1.3.RELEASE</version><relativePath/> <!-- lookup parent from repository --></parent><groupId>com.cjs.sso</groupId><artifactId>oauth2-sso-auth-server</artifactId><version>0.0.1-SNAPSHOT</version><name>oauth2-sso-auth-server</name><properties><java.version>1.8</java.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-jpa</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-security</artifactId></dependency><dependency><groupId>org.springframework.security.oauth.boot</groupId><artifactId>spring-security-oauth2-autoconfigure</artifactId><version>2.1.3.RELEASE</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-thymeleaf</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.session</groupId><artifactId>spring-session-data-redis</artifactId></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><scope>runtime</scope></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><dependency><groupId>org.springframework.security</groupId><artifactId>spring-security-test</artifactId><scope>test</scope></dependency><dependency><groupId>org.apache.commons</groupId><artifactId>commons-lang3</artifactId><version>3.8.1</version></dependency><dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.56</version></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build></project>

這里面最重要的依賴是:spring-security-oauth2-autoconfigure

4.2. application.yml

spring:datasource:url: jdbc:mysql://localhost:3306/permissionusername: rootpassword: 123456driver-class-name: com.mysql.jdbc.Driverjpa:show-sql: truesession:store-type: redisredis:host: 127.0.0.1password: 123456port: 6379 server:port: 8080

4.3. AuthorizationServerConfig(重要)

package com.cjs.sso.config;import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Primary; import org.springframework.security.core.token.DefaultToken; import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer; import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter; import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer; import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer; import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer; import org.springframework.security.oauth2.provider.token.DefaultTokenServices; import org.springframework.security.oauth2.provider.token.TokenStore; import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter; import org.springframework.security.oauth2.provider.token.store.JwtTokenStore;import javax.sql.DataSource;/*** @author ChengJianSheng* @date 2019-02-11*/ @Configuration @EnableAuthorizationServer public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {@Autowiredprivate DataSource dataSource;@Overridepublic void configure(AuthorizationServerSecurityConfigurer security) throws Exception {security.allowFormAuthenticationForClients();security.tokenKeyAccess("isAuthenticated()");}@Overridepublic void configure(ClientDetailsServiceConfigurer clients) throws Exception {clients.jdbc(dataSource);}@Overridepublic void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {endpoints.accessTokenConverter(jwtAccessTokenConverter());endpoints.tokenStore(jwtTokenStore()); // endpoints.tokenServices(defaultTokenServices());}/*@Primary@Beanpublic DefaultTokenServices defaultTokenServices() {DefaultTokenServices defaultTokenServices = new DefaultTokenServices();defaultTokenServices.setTokenStore(jwtTokenStore());defaultTokenServices.setSupportRefreshToken(true);return defaultTokenServices;}*/@Beanpublic JwtTokenStore jwtTokenStore() {return new JwtTokenStore(jwtAccessTokenConverter());}@Beanpublic JwtAccessTokenConverter jwtAccessTokenConverter() {JwtAccessTokenConverter jwtAccessTokenConverter = new JwtAccessTokenConverter();jwtAccessTokenConverter.setSigningKey("cjs"); // Sets the JWT signing keyreturn jwtAccessTokenConverter;}}

說明:

  • 別忘了**@EnableAuthorizationServer**

  • Token存儲采用的是JWT

  • 客戶端以及登錄用戶這些配置存儲在數據庫,為了減少數據庫的查詢次數,可以從數據庫讀出來以后再放到內存中

  • 4.4. WebSecurityConfig(重要)

    package com.cjs.sso.config;import com.cjs.sso.service.MyUserDetailsService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.builders.WebSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder;/*** @author ChengJianSheng* @date 2019-02-11*/ @Configuration @EnableWebSecurity public class WebSecurityConfig extends WebSecurityConfigurerAdapter {@Autowiredprivate MyUserDetailsService userDetailsService;@Overrideprotected void configure(AuthenticationManagerBuilder auth) throws Exception {auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());}@Overridepublic void configure(WebSecurity web) throws Exception {web.ignoring().antMatchers("/assets/**", "/css/**", "/images/**");}@Overrideprotected void configure(HttpSecurity http) throws Exception {http.formLogin().loginPage("/login").and().authorizeRequests().antMatchers("/login").permitAll().anyRequest().authenticated().and().csrf().disable().cors();}@Beanpublic PasswordEncoder passwordEncoder() {return new BCryptPasswordEncoder();}}

    4.5. 自定義登錄頁面(一般來講都是要自定義的)

    package com.cjs.sso.controller;import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.GetMapping;/*** @author ChengJianSheng* @date 2019-02-12*/ @Controller public class LoginController {@GetMapping("/login")public String login() {return "login";}@GetMapping("/")public String index() {return "index";}}

    自定義登錄頁面的時候,只需要準備一個登錄頁面,然后寫個Controller令其可以訪問到即可,登錄頁面表單提交的時候method一定要是post,最重要的時候action要跟訪問登錄頁面的url一樣

    千萬記住了,訪問登錄頁面的時候是GET請求,表單提交的時候是POST請求,其它的就不用管了

    <!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org"> <head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><title>Ela Admin - HTML5 Admin Template</title><meta name="description" content="Ela Admin - HTML5 Admin Template"><meta name="viewport" content="width=device-width, initial-scale=1"><link type="text/css" rel="stylesheet" th:href="@{/assets/css/normalize.css}"><link type="text/css" rel="stylesheet" th:href="@{/assets/bootstrap-4.3.1-dist/css/bootstrap.min.css}"><link type="text/css" rel="stylesheet" th:href="@{/assets/css/font-awesome.min.css}"><link type="text/css" rel="stylesheet" th:href="@{/assets/css/style.css}"></head> <body class="bg-dark"><div class="sufee-login d-flex align-content-center flex-wrap"><div class="container"><div class="login-content"><div class="login-logo"><h1 style="color: #57bf95;">歡迎來到王者榮耀</h1></div><div class="login-form"><form th:action="@{/login}" method="post"><div class="form-group"><label>Username</label><input type="text" class="form-control" name="username" placeholder="Username"></div><div class="form-group"><label>Password</label><input type="password" class="form-control" name="password" placeholder="Password"></div><div class="checkbox"><label><input type="checkbox"> Remember Me</label><label class="pull-right"><a href="#">Forgotten Password?</a></label></div><button type="submit" class="btn btn-success btn-flat m-b-30 m-t-30" style="font-size: 18px;">登錄</button></form></div></div></div> </div><script type="text/javascript" th:src="@{/assets/js/jquery-2.1.4.min.js}"></script> <script type="text/javascript" th:src="@{/assets/bootstrap-4.3.1-dist/js/bootstrap.min.js}"></script> <script type="text/javascript" th:src="@{/assets/js/main.js}"></script></body> </html>

    4.6. 定義客戶端

    4.7. 加載用戶

    登錄賬戶

    package com.cjs.sso.domain;import lombok.Data; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.userdetails.User;import java.util.Collection;/*** 大部分時候直接用User即可不必擴展* @author ChengJianSheng* @date 2019-02-11*/ @Data public class MyUser extends User {private Integer departmentId; // 舉個例子,部門IDprivate String mobile; // 舉個例子,假設我們想增加一個字段,這里我們增加一個mobile表示手機號public MyUser(String username, String password, Collection<? extends GrantedAuthority> authorities) {super(username, password, authorities);}public MyUser(String username, String password, boolean enabled, boolean accountNonExpired, boolean credentialsNonExpired, boolean accountNonLocked, Collection<? extends GrantedAuthority> authorities) {super(username, password, enabled, accountNonExpired, credentialsNonExpired, accountNonLocked, authorities);} }

    加載登錄賬戶

    package com.cjs.sso.service;import com.alibaba.fastjson.JSON; import com.cjs.sso.domain.MyUser; import com.cjs.sso.entity.SysPermission; import com.cjs.sso.entity.SysUser; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.core.userdetails.UsernameNotFoundException; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.stereotype.Service; import org.springframework.util.CollectionUtils;import java.util.ArrayList; import java.util.List;/*** @author ChengJianSheng* @date 2019-02-11*/ @Slf4j @Service public class MyUserDetailsService implements UserDetailsService {@Autowiredprivate PasswordEncoder passwordEncoder;@Autowiredprivate UserService userService;@Autowiredprivate PermissionService permissionService;@Overridepublic UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {SysUser sysUser = userService.getByUsername(username);if (null == sysUser) {log.warn("用戶{}不存在", username);throw new UsernameNotFoundException(username);}List<SysPermission> permissionList = permissionService.findByUserId(sysUser.getId());List<SimpleGrantedAuthority> authorityList = new ArrayList<>();if (!CollectionUtils.isEmpty(permissionList)) {for (SysPermission sysPermission : permissionList) {authorityList.add(new SimpleGrantedAuthority(sysPermission.getCode()));}}MyUser myUser = new MyUser(sysUser.getUsername(), passwordEncoder.encode(sysUser.getPassword()), authorityList);log.info("登錄成功!用戶: {}", JSON.toJSONString(myUser));return myUser;} }

    4.8. 驗證

    當我們看到這個界面的時候,表示認證服務器配置完成

    5. 兩個客戶端

    5.1. Maven依賴

    <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.1.3.RELEASE</version><relativePath/> <!-- lookup parent from repository --></parent><groupId>com.cjs.sso</groupId><artifactId>oauth2-sso-client-member</artifactId><version>0.0.1-SNAPSHOT</version><name>oauth2-sso-client-member</name><description>Demo project for Spring Boot</description><properties><java.version>1.8</java.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-jpa</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-oauth2-client</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-security</artifactId></dependency><dependency><groupId>org.springframework.security.oauth.boot</groupId><artifactId>spring-security-oauth2-autoconfigure</artifactId><version>2.1.3.RELEASE</version></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><version>3.0.4.RELEASE</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>com.h2database</groupId><artifactId>h2</artifactId><scope>runtime</scope></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><dependency><groupId>org.springframework.security</groupId><artifactId>spring-security-test</artifactId><scope>test</scope></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build></project>

    5.2. application.yml

    server:port: 8082servlet:context-path: /memberSystem security:oauth2:client:client-id: UserManagementclient-secret: user123access-token-uri: http://localhost:8080/oauth/tokenuser-authorization-uri: http://localhost:8080/oauth/authorizeresource:jwt:key-uri: http://localhost:8080/oauth/token_key

    這里context-path不要設成/,不然重定向獲取code的時候回被攔截

    5.3. WebSecurityConfig

    package com.cjs.example.config;import com.cjs.example.util.EnvironmentUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.security.oauth2.client.EnableOAuth2Sso; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.builders.WebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;/*** @author ChengJianSheng* @date 2019-03-03*/ @EnableOAuth2Sso @Configuration public class WebSecurityConfig extends WebSecurityConfigurerAdapter {@Autowiredprivate EnvironmentUtils environmentUtils;@Overridepublic void configure(WebSecurity web) throws Exception {web.ignoring().antMatchers("/bootstrap/**");}@Overrideprotected void configure(HttpSecurity http) throws Exception {if ("local".equals(environmentUtils.getActiveProfile())) {http.authorizeRequests().anyRequest().permitAll();}else {http.logout().logoutSuccessUrl("http://localhost:8080/logout").and().authorizeRequests().anyRequest().authenticated().and().csrf().disable();}} }

    說明:

  • 最重要的注解是@EnableOAuth2Sso

  • 權限控制這里采用Spring Security方法級別的訪問控制,結合Thymeleaf可以很容易做權限控制

  • 順便多提一句,如果是前后端分離的話,前端需求加載用戶的權限,然后判斷應該顯示那些按鈕那些菜單

  • 5.4. MemberController

    package com.cjs.example.controller;import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.security.core.Authentication; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody;import java.security.Principal;/*** @author ChengJianSheng* @date 2019-03-03*/ @Controller @RequestMapping("/member") public class MemberController {@GetMapping("/list")public String list() {return "member/list";}@GetMapping("/info")@ResponseBodypublic Principal info(Principal principal) {return principal;}@GetMapping("/me")@ResponseBodypublic Authentication me(Authentication authentication) {return authentication;}@PreAuthorize("hasAuthority('member:save')")@ResponseBody@PostMapping("/add")public String add() {return "add";}@PreAuthorize("hasAuthority('member:detail')")@ResponseBody@GetMapping("/detail")public String detail() {return "detail";} }

    5.5. Order項目跟它是一樣的

    server:port: 8083servlet:context-path: /orderSystem security:oauth2:client:client-id: OrderManagementclient-secret: order123access-token-uri: http://localhost:8080/oauth/tokenuser-authorization-uri: http://localhost:8080/oauth/authorizeresource:jwt:key-uri: http://localhost:8080/oauth/token_key

    5.6. 關于退出

    退出就是清空用于與SSO客戶端建立的所有的會話,簡單的來說就是使所有端點的Session失效,如果想做得更好的話可以令Token失效,但是由于我們用的JWT,故而撤銷Token就不是那么容易,關于這一點,在官網上也有提到:

    本例中采用的方式是在退出的時候先退出業務服務器,成功以后再回調認證服務器,但是這樣有一個問題,就是需要主動依次調用各個業務服務器的logout

    6. 工程結構

    附上源碼:https://github.com/chengjiansheng/cjs-oauth2-sso-demo.git

    7. 演示

    8. 參考

    https://www.cnblogs.com/cjsblog/p/9174797.html

    https://www.cnblogs.com/cjsblog/p/9184173.html

    https://www.cnblogs.com/cjsblog/p/9230990.html

    https://www.cnblogs.com/cjsblog/p/9277677.html

    https://blog.csdn.net/fooelliot/article/details/83617941

    http://blog.leapoahead.com/2015/09/07/user-authentication-with-jwt/

    https://www.cnblogs.com/lihaoyang/p/8581077.html

    https://www.cnblogs.com/charlypage/p/9383420.html

    http://www.360doc.com/content/18/0306/17/16915_734789216.shtml

    https://blog.csdn.net/chenjianandiyi/article/details/78604376

    https://www.baeldung.com/spring-security-oauth-jwt

    https://www.baeldung.com/spring-security-oauth-revoke-tokens

    https://www.reinforce.cn/t/630.html

    9. 文檔

    https://projects.spring.io/spring-security-oauth/docs/oauth2.html

    https://docs.spring.io/spring-security-oauth2-boot/docs/2.1.3.RELEASE/reference/htmlsingle/

    https://docs.spring.io/spring-security-oauth2-boot/docs/2.1.3.RELEASE/

    https://docs.spring.io/spring-security-oauth2-boot/docs/

    https://docs.spring.io/spring-boot/docs/2.1.3.RELEASE/

    https://docs.spring.io/spring-boot/docs/

    https://docs.spring.io/spring-framework/docs/

    https://docs.spring.io/spring-framework/docs/5.1.4.RELEASE/

    https://spring.io/guides/tutorials/spring-boot-oauth2/

    https://docs.spring.io/spring-security/site/docs/current/reference/htmlsingle/#core-services-password-encoding

    https://spring.io/projects/spring-cloud-security

    https://cloud.spring.io/spring-cloud-security/single/spring-cloud-security.html

    https://docs.spring.io/spring-session/docs/current/reference/html5/guides/java-security.html

    https://docs.spring.io/spring-session/docs/current/reference/html5/guides/boot-redis.html#boot-spring-configuration

    創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎

    總結

    以上是生活随笔為你收集整理的OAuth2 实现单点登录 SSO的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。