springboot oauth2實(shí)現(xiàn)單點(diǎn)登錄實(shí)例
我們見(jiàn)過(guò)的很多網(wǎng)站,容許使用第三方賬號(hào)登錄,他不需要關(guān)注用戶(hù)信息,只需要用戶(hù)拿到授權(quán)碼就可以訪問(wèn)。
oauth2是用來(lái)做三方登錄的,他的授權(quán)方式有好幾種,授權(quán)碼模式、密碼模式、隱式模式、客戶(hù)端模式。
oauth2認(rèn)證的過(guò)程如下:一般我們請(qǐng)求一個(gè)需要登錄的網(wǎng)站A,會(huì)提示我們使用第三方網(wǎng)站C的用戶(hù)登錄,我們登錄,這時(shí)候需要我們授權(quán),就是authorize,授權(quán)之后,會(huì)得到一個(gè)token,我們拿到這個(gè)token就可以訪問(wèn)這個(gè)網(wǎng)站A了。A網(wǎng)站不關(guān)心C網(wǎng)站的用戶(hù)信息。
springsecurity結(jié)合oauth2可以做這個(gè)功能,這里給出一個(gè)springboot+security+oauth2的實(shí)例,這個(gè)實(shí)例很直觀,就是我們有兩個(gè)服務(wù)A,C,A是需要用戶(hù)登錄的網(wǎng)站,而C是授權(quán)服務(wù)器。當(dāng)我們?cè)L問(wèn)A的資源:http://localhost:8000/hello,他會(huì)跳到C的服務(wù)器上登錄,登錄完成,授權(quán),就直接調(diào)回來(lái)A網(wǎng)站,這里使用了單點(diǎn)登錄功能。
構(gòu)建項(xiàng)目:我這里構(gòu)建了一個(gè)父級(jí)項(xiàng)目securityoauth2,然后加入了兩個(gè)模塊:auth-server,client-1。

項(xiàng)目依賴(lài):
securityoauth2->pom.xml
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.4.RELEASE</version> </parent> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> <dependency> <groupId>org.springframework.security.oauth</groupId> <artifactId>spring-security-oauth2</artifactId> <version>2.3.4.RELEASE</version> </dependency> <dependency> <groupId>org.springframework.security.oauth.boot</groupId> <artifactId>spring-security-oauth2-autoconfigure</artifactId> <version>2.3.2.RELEASE</version> </dependency> </dependencies> <modules> <module>auth-server</module> <module>client-1</module> </modules>
***********auth-server***************************************

AuthServerConfiguration.java
package com.xxx.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.crypto.password.PasswordEncoder;
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;
@Configuration
@EnableAuthorizationServer
public class AuthServerConfiguration extends AuthorizationServerConfigurerAdapter{
@Autowired
private PasswordEncoder passwordEncoder;
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.inMemory()
.withClient("client")
.secret(passwordEncoder.encode("secret"))
.autoApprove(true)
.redirectUris("http://localhost:8000/login","http://localhost:8001/login")
.scopes("user")
.accessTokenValiditySeconds(7200)
.authorizedGrantTypes("authorization_code");
}
}授權(quán)服務(wù)配置這里,主要設(shè)置client_id,以及secret,這里設(shè)置了自動(dòng)授權(quán)autoApprove(true),就是我們輸入用戶(hù)名和密碼登錄之后,不會(huì)出現(xiàn)一個(gè)需要我們手動(dòng)點(diǎn)擊authorize的按鈕進(jìn)行授權(quán)。另外配置了redirect_uri,這個(gè)是必須的。最后還設(shè)置了授權(quán)類(lèi)型,這里選擇的是授權(quán)碼模式。
SecurityConfiguration.java
package com.xxx.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
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.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;
@Configuration
@Order(1)
@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter{
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Override
protected void configure(AuthenticationManagerBuilder builder) throws Exception {
builder.inMemoryAuthentication()
.withUser("admin")
.password(passwordEncoder().encode("admin"))
.roles("admin");
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.requestMatchers()
.antMatchers("/login")
.antMatchers("/oauth/authorize")
.and()
.authorizeRequests().anyRequest().authenticated()
.and()
.formLogin()
.and()
.csrf().disable();
}
}Security是做權(quán)限管理的,他需要配置用戶(hù)和密碼,這里采用內(nèi)存保存的方式,將用戶(hù)名和密碼保存在內(nèi)存中,而不是數(shù)據(jù)庫(kù)或者redis中,關(guān)于保存在哪里,對(duì)于了解oauth2來(lái)說(shuō),放在內(nèi)存是最簡(jiǎn)單的,省去了建表,做數(shù)據(jù)庫(kù)查詢(xún)的麻煩。
TestController.java
package com.xxx.web;
import java.security.Principal;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/api/test")
public class TestController {
@GetMapping("/user")
public Principal currentUser(Principal principal) {
return principal;
}
}這個(gè)controller配置,不是用來(lái)測(cè)試訪問(wèn)他的,而是用來(lái)做一個(gè)接口,給client-1使用,client-1配置文件中有個(gè)配置:security.oauth2.resource.user-info-uri就是配置的這個(gè)接口。
App.java
package com.xxx;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
@SpringBootApplication
@EnableResourceServer
public class App {
public static void main( String[] args ){
SpringApplication.run(App.class, args);
}
}application.yaml //無(wú)配置,可以略
***********client-1*********************************************************

SecurityConfiguration.java
package com.xxx.config;
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.configuration.WebSecurityConfigurerAdapter;
@SuppressWarnings("deprecation")
@Configuration
@EnableOAuth2Sso
public class SecurityConfiguration extends WebSecurityConfigurerAdapter{
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().anyRequest().authenticated().and().csrf().disable();
}
}TestController.java
package com.xxx.web;
import java.util.Arrays;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class TestController {
@GetMapping("/hello")
public String hello() {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
return authentication.getName()+Arrays.toString(authentication.getAuthorities().toArray());
}
}App.java
package com.xxx;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class App {
public static void main( String[] args ){
SpringApplication.run(App.class, args);
}
}application.yaml
server:
port: 8000
servlet:
session:
cookie:
name: s1
security:
oauth2:
client:
client-id: client
client-secret: secret
user-authorization-uri: http://localhost:8080/oauth/authorize
access-token-uri: http://localhost:8080/oauth/token
resource:
user-info-uri: http://localhost:8080/api/test/user以上都是代碼部分,下面主要是測(cè)試,測(cè)試過(guò)程很簡(jiǎn)單,就是我們啟動(dòng)兩個(gè)服務(wù),打開(kāi)瀏覽器訪問(wèn)client-1的http://localhost:8000/hello接口,這時(shí)候因?yàn)樾枰卿洠瑫?huì)跳轉(zhuǎn)到auth-server服務(wù)的http://localhost:8080/login,登錄成功,會(huì)接著訪問(wèn)授權(quán)接口,授權(quán)成功,會(huì)跳轉(zhuǎn)到http://localhost:8000/login,然后跳轉(zhuǎn)到http://localhost:8000/hello,貌似很復(fù)雜,我們先看看效果:

值得注意的是,如圖所示的2、3順序,在這個(gè)結(jié)果頁(yè)面是這樣的,但是在登錄頁(yè)面并不是這樣,而是先3后2:

可以這么解釋?zhuān)篶lient-1的接口http://localhost:8000/hello需要權(quán)限才能訪問(wèn),這時(shí)候,需要登錄自己的系統(tǒng)http://localhost:8000/login,而自己的系統(tǒng)支持oauth2,他通過(guò)封裝了client_id,response_type,redirect_uri,state等參數(shù)的授權(quán)碼模式請(qǐng)求接口,向auth-server服務(wù)發(fā)起授權(quán)請(qǐng)求http://localhost:8080/oauth/authorize?client_id=client&redirect_uri=http://localhost:8000/login&response_type=code&state=PphcA2,請(qǐng)求會(huì)跳轉(zhuǎn)auth-server的登錄頁(yè)面 http://localhost:8080/login。
這里因?yàn)槭褂昧藛吸c(diǎn)登錄,先從client-1跳轉(zhuǎn)到了auth-server,最后拿到了code之后,跳回了client-1,訪問(wèn)成功。而頁(yè)面上顯示的內(nèi)容并不是一開(kāi)始就是這樣子的,他會(huì)先跳轉(zhuǎn)auth-server登錄頁(yè)面:

以上代碼有了,結(jié)果也驗(yàn)證了,但是個(gè)人還是不是很了解這個(gè)登錄授權(quán)的原理和過(guò)程,也是在學(xué)習(xí)中,這個(gè)所謂的單點(diǎn)登陸,在代碼上就用了一個(gè)@EnableOAuth2Sso注解在client-1項(xiàng)目的SecurityConfiguration類(lèi)上,該類(lèi)也是繼承自WebSecurityConfigurerAdapter類(lèi),然后覆蓋了configure(HttpSecurity http)方法。
到此這篇關(guān)于springboot oauth2實(shí)現(xiàn)單點(diǎn)登錄實(shí)例的文章就介紹到這了,更多相關(guān)springboot oauth2單點(diǎn)登錄內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- SpringBoot3.X配置OAuth的代碼實(shí)踐
- SpringBoot的Security和OAuth2的使用示例小結(jié)
- 使用Springboot實(shí)現(xiàn)OAuth服務(wù)的示例詳解
- SpringBoot淺析安全管理之OAuth2框架
- springboot集成springsecurity 使用OAUTH2做權(quán)限管理的教程
- 基于SpringBoot整合oauth2實(shí)現(xiàn)token認(rèn)證
- springboot2.x實(shí)現(xiàn)oauth2授權(quán)碼登陸的方法
- 詳解Springboot Oauth2 Server搭建Oauth2認(rèn)證服務(wù)
- 使用Springboot搭建OAuth2.0 Server的方法示例
- SpringBoot集成OAuth2.0的實(shí)現(xiàn)示例
相關(guān)文章
Java實(shí)現(xiàn)順時(shí)針輸出螺旋二維數(shù)組的方法示例
這篇文章主要介紹了利用Java如何實(shí)現(xiàn)順時(shí)針輸出螺旋二維數(shù)組的方法示例,文中給出了詳細(xì)的示例代碼和注釋?zhuān)嘈艑?duì)大家具有一定的參考價(jià)值,有需要的朋友們下面來(lái)一起看看吧。2017-02-02
Java實(shí)現(xiàn)SHA-256加密算法的完全解析
SHA-256是一種散列(哈希)算法,用于將任意長(zhǎng)度的數(shù)據(jù)映射為固定長(zhǎng)度的散列值,以保證數(shù)據(jù)完整性。本文將為大家介紹一下SHA-256加密算法的原理與實(shí)現(xiàn),希望對(duì)大家有所幫助2023-02-02
關(guān)于eclipse安裝spring插件報(bào)錯(cuò)An error occurred while collecting item
這篇文章主要介紹了關(guān)于eclipse安裝spring插件報(bào)錯(cuò)An error occurred while collecting items to be installed...解決方案,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-08-08
java實(shí)現(xiàn)操作系統(tǒng)中的最佳置換Optimal算法
這篇文章主要介紹了java實(shí)現(xiàn)操作系統(tǒng)中的最佳置換Optimal算法 ,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-02-02
Mybatis plus中的like查詢(xún)問(wèn)題
這篇文章主要介紹了Mybatis plus中的like查詢(xún)問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-06-06
springboot項(xiàng)目中jackson-序列化-處理 NULL教程
這篇文章主要介紹了springboot項(xiàng)目中jackson-序列化-處理 NULL教程,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-10-10

