SpringBoot的Security和OAuth2的使用示例小結(jié)
創(chuàng)建項(xiàng)目
先創(chuàng)建一個(gè)spring項(xiàng)目。
然后編寫pom文件如下,引入spring-boot-starter-security,我這里使用的spring boot是2.4.2,這里使用使用spring-boot-dependencies,在這里就能找到對(duì)應(yīng)的security的包。
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>app-kiba-security</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>app-kiba-security</name>
<description>app-kiba-security</description>
<properties>
<java.version>1.8</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<spring-boot.version>2.4.2</spring-boot.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>${spring-boot.version}</version>
<configuration>
<mainClass>com.kiba.appkibasecurity.AppKibaSecurityApplication</mainClass>
<skip>true</skip>
</configuration>
<executions>
<execution>
<id>repackage</id>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>然后訪問創(chuàng)建項(xiàng)目時(shí)默認(rèn)生成的接口:http://127.0.0.1:8080/user/123/roles/222,得到如下界面。

這是相當(dāng)于,在我們的接口請(qǐng)求的前面做了一個(gè)攔截,類似filter,攔截后,跳轉(zhuǎn)到了一個(gè)界面,讓我們輸入賬號(hào)密碼。這里,我由于沒有設(shè)置賬號(hào)密碼,所以登錄不進(jìn)去。
設(shè)置訪問一
下面設(shè)置一個(gè)賬號(hào)密碼,并且設(shè)置hello接口可以直接訪問,設(shè)置很簡單,就是注入兩個(gè)bean,InMemoryUserDetailsManager和WebSecurityCustomizer,代碼如下:
@Configuration
public class SecurityConfig {
/**
* 注冊(cè)用戶,這里用戶是在內(nèi)存中的
* {noop}表示“無操作”(No Operation)密碼編碼。
* @return
*/
@Bean
UserDetailsService userDetailsService() {
InMemoryUserDetailsManager users = new InMemoryUserDetailsManager();
users.createUser(User.withUsername("kiba").password("{noop}123").roles("admin").build());
return users;
}
/**
* 讓hello可以不用登錄,就可以直接訪問,例如:http://127.0.0.1:8080/hello?name=kiba就可以直接訪問
* @return
*/
@Bean
WebSecurityCustomizer webSecurityCustomizer() {
return new WebSecurityCustomizer() {
@Override
public void customize(WebSecurity web) {
web.ignoring().antMatchers("/hello");
}
};
}
}現(xiàn)在我們?cè)L問http://127.0.0.1:8080/user/123/roles/222,進(jìn)入到登錄頁面,輸入kiba/123就可以查看接口執(zhí)行的結(jié)果了。
http://127.0.0.1:8080/hello?name=kiba就無需登錄,可以直接訪問。
登錄一次,其他接口就可以自由訪問了
控制請(qǐng)求
現(xiàn)在,增加一個(gè)類SecurityAdapter,繼承自WebSecurityConfigurerAdapter。然后重寫他的configure方法
@Configuration
@AllArgsConstructor
public class SecurityAdapter extends WebSecurityConfigurerAdapter {
/**
* authenticated():用戶需要通過用戶名/密碼登錄,記住我功能也可以(remember-me)。
* fullyAuthenticated()用戶需要通過用戶名/密碼登錄,記住我功能不行。
*/
@Override
@SneakyThrows
protected void configure(HttpSecurity http) {
http.httpBasic().and()
//禁用跨站請(qǐng)求偽造(CSRF)保護(hù)。
.csrf().disable()
.authorizeRequests().anyRequest().fullyAuthenticated();
}
}當(dāng)使用,增加了SecurityAdapter后,我們重新請(qǐng)求http://127.0.0.1:8080/user/123/roles/222,得到界面如下:

可以看到,登錄界面的樣式被美化了。
設(shè)置訪問二(推薦)
我們還可以使用第二種方法,來做用戶密碼的配置。
通過重寫configure(AuthenticationManagerBuilder auth)函數(shù),來創(chuàng)建用戶,這種方式創(chuàng)建用戶會(huì)將前面的bean-UserDetailsService給覆蓋,即,用戶只剩下這里創(chuàng)建的。
代碼如下:
@Configuration
@AllArgsConstructor
public class SecurityAdapter extends WebSecurityConfigurerAdapter {
/**
* authenticated():用戶需要通過用戶名/密碼登錄,記住我功能也可以(remember-me)。
* fullyAuthenticated()用戶需要通過用戶名/密碼登錄,記住我功能不行。
*/
@Override
@SneakyThrows
protected void configure(HttpSecurity http) {
http.httpBasic().and()
//禁用跨站請(qǐng)求偽造(CSRF)保護(hù)。
.csrf().disable()
.authorizeRequests().anyRequest().fullyAuthenticated();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("kiba518")
.password(passwordEncoder().encode("123"))
.authorities(new ArrayList<>(0));
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}這里的用戶是寫死的,用戶是可以修改成讀取數(shù)據(jù)庫的信息的。
我們查看WebSecurityConfigurerAdapter的代碼,可以看到他有注解@Order(100),數(shù)越大,執(zhí)行越優(yōu)先級(jí)越低,即,他的執(zhí)行順序是相對(duì)比較靠后的。
授權(quán)OAuth2
授權(quán)這個(gè)設(shè)計(jì)理念是這樣,它是結(jié)合上面的security的操作,實(shí)現(xiàn)了一個(gè)普通的WebApp轉(zhuǎn)換成授權(quán)服務(wù)器WebApp。
授權(quán)服務(wù)器轉(zhuǎn)換思路
我們先了解一下security轉(zhuǎn)授權(quán)服務(wù)器的思路。
1,在這個(gè)應(yīng)用里,創(chuàng)建一個(gè)auth接口,然后任何人想訪問這個(gè)接口,就都需要輸入賬戶密碼了。
2,我們這個(gè)auth接口的返回值是個(gè)code,然后我們的前端,或者其他調(diào)用接口的APP,就可以把這個(gè)code作為用戶登錄的token了,。
3,然后我們?cè)僮鲆粋€(gè)接口,接受一個(gè)token參數(shù),可以驗(yàn)證token是否有效。
這樣我們這個(gè)授權(quán)服務(wù)器的搭建思路就構(gòu)建完成了。
但按這個(gè)思路,我們需要做很多操作,比如創(chuàng)建接口,緩存token等等,現(xiàn)在spring提供了一個(gè)Oauth2的包,他可以幫我們實(shí)現(xiàn)這些接口定義。
OAuth2的接口如下,可以自行研究。
/oauth/authorize:授權(quán)端點(diǎn)
/oauth/token:獲取令牌端點(diǎn)
/oauth/confirm_access:用戶確認(rèn)授權(quán)提交端點(diǎn)
/oauth/error:授權(quán)服務(wù)錯(cuò)誤信息端點(diǎn)
/oauth/check_token:用于資源服務(wù)訪問的令牌解析端點(diǎn)
/oauth/token_key:提供公有密匙的端點(diǎn),如果使用JWT令牌的話
實(shí)現(xiàn)授權(quán)服務(wù)器
現(xiàn)在我們實(shí)現(xiàn)一個(gè)授權(quán)服務(wù)器。
先添加OAuth2的引用。
<dependency>
<groupId>org.springframework.security.oauth</groupId>
<artifactId>spring-security-oauth2</artifactId>
<version>2.4.0.RELEASE</version>
</dependency>然后增加配置文件AuthorizationConfig。
@Configuration
@EnableAuthorizationServer //開啟授權(quán)服務(wù)
public class AuthorizationConfig extends AuthorizationServerConfigurerAdapter {
@Autowired
private PasswordEncoder passwordEncoder;
@Autowired
private AuthenticationManager authenticationManager;
@Override
public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
//允許表單提交
security.allowFormAuthenticationForClients()
.checkTokenAccess("isAuthenticated()");
}
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.inMemory()
.withClient("client-kiba") //客戶端唯一標(biāo)識(shí)(client_id)
.secret(passwordEncoder.encode("kiba518-123456")) //客戶端的密碼(client_secret),這里的密碼應(yīng)該是加密后的
.authorizedGrantTypes("password") //授權(quán)模式標(biāo)識(shí),共4種模式[授權(quán)碼(authorization-code)隱藏式(implicit) 密碼式(password)客戶端憑證(client credentials)]
.scopes("read_scope"); //作用域
}
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints.authenticationManager(authenticationManager);
}
}然后打開SecurityAdapter,增加一個(gè)bean,如下,目的是讓上面的AuthorizationConfig里Autowired的authenticationManager可以實(shí)例化。
@Bean
public AuthenticationManager authenticationManager() throws Exception {
return super.authenticationManager();
}然后使用APIFox調(diào)用一下/oauth/token接口。
先選擇auth,輸入賬號(hào)密碼,這個(gè)賬號(hào)密碼就是AuthorizationConfig里配置的客戶端id和密碼。

這個(gè)數(shù)據(jù)在請(qǐng)求時(shí),會(huì)進(jìn)行base64編碼,然后以http的header屬性Authorization的值的模式傳遞,如下。

然后輸入?yún)?shù),參數(shù)里scope和grant_type要和AuthorizationConfig里定義的scopes和authorizedGrantTypes一樣,如下。

請(qǐng)求后,得到結(jié)果,如上圖。
我們得到"access_token": "19d37af2-6e13-49c3-bf19-30a738b56886"。
有了access_token后,我們的前端其實(shí)就已經(jīng)可以進(jìn)行各種騷操作了。
資源服務(wù)
這個(gè)是Oauth為我們提供的一項(xiàng)很好用的功能。
我們創(chuàng)建一個(gè)項(xiàng)目做為資源服務(wù)。
添加依賴,版本與上面相同。
<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.4.0.RELEASE</version>
</dependency>然后編寫資源配置,代碼如下:
@Configuration
@EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {
@Bean
public RemoteTokenServices remoteTokenServices() {
final RemoteTokenServices tokenServices = new RemoteTokenServices();
tokenServices.setClientId("client-kiba");
tokenServices.setClientSecret("kiba518-123456");
tokenServices.setCheckTokenEndpointUrl("http://localhost:8080/oauth/check_token");//這個(gè)接口是oauth自帶的
return tokenServices;
}
@Override
public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
resources.stateless(true);
}
@Override
public void configure(HttpSecurity http) throws Exception {
//session創(chuàng)建策略
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED);
//所有請(qǐng)求需要認(rèn)證
http.authorizeRequests().anyRequest().authenticated();
}
}因?yàn)樘砑恿藄pring-boot-starter-security,所以,我們請(qǐng)求這個(gè)資源WebApp,就都需要輸入賬號(hào)密碼。
但因?yàn)?,我們配置了ResourceServerConfig,這里我們配置了遠(yuǎn)程token服務(wù),設(shè)置的信息是我們上面創(chuàng)建授權(quán)服務(wù)的信息。所以,在訪問這個(gè)WebApp時(shí),我們提供token即可。
使用APIFOX測(cè)試,先添加auth的token,內(nèi)容是來自于上面,/oauth/token的返回值access_token的值。

然后請(qǐng)求user接口,我這user接口沒有參數(shù),請(qǐng)求結(jié)果如下:

總結(jié)
這個(gè)授權(quán)服務(wù)挺好用的,就是配置太繁瑣了,初學(xué)者不太好理解,而且功能太多,配置太鬧心。
這個(gè)資源服務(wù)還是很貼心的,他提我們實(shí)現(xiàn)了,tokencheck的部分,但要注意的是,他這tokencheck是基于http請(qǐng)求的。
雖然Oath很好用,但,我還是覺得,這個(gè)認(rèn)證部分自己寫比較好,我們可以根據(jù)項(xiàng)目的需求,設(shè)計(jì)輕量級(jí)的授權(quán)認(rèn)證。
比如,我們想減少http請(qǐng)求,把部分tokencheck在緩存內(nèi)進(jìn)行check,那使用oauth時(shí),修改起來就會(huì)很頭疼。如果是自己寫的授權(quán)服務(wù)器,就不會(huì)有修改困難的問題。
注:此文章為原創(chuàng),任何形式的轉(zhuǎn)載都請(qǐng)聯(lián)系作者獲得授權(quán)并注明出處!
https://www.cnblogs.com/kiba/p/18252859
到此這篇關(guān)于SpringBoot的Security和OAuth2的使用的文章就介紹到這了,更多相關(guān)SpringBoot的Security和OAuth2的使用內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- SpringBoot3.X配置OAuth的代碼實(shí)踐
- 使用Springboot實(shí)現(xiàn)OAuth服務(wù)的示例詳解
- SpringBoot淺析安全管理之OAuth2框架
- springboot oauth2實(shí)現(xiàn)單點(diǎn)登錄實(shí)例
- 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)在Excel中添加動(dòng)態(tài)數(shù)組公式
動(dòng)態(tài)數(shù)組公式是?Excel?引入的一項(xiàng)重要功能,它允許用戶從單個(gè)單元格中的公式返回多個(gè)結(jié)果值,并將這些值自動(dòng)填充到與公式單元格相鄰的單元格中,本文主要介紹了如何使用Java實(shí)現(xiàn)在Excel中添加動(dòng)態(tài)數(shù)組公式,x需要的可以參考下2023-12-12
Servlet和Spring?MVC的區(qū)別及使用說明
這篇文章詳細(xì)介紹了Servlet和SpringMVC的基本概念、工作原理、功能對(duì)比和應(yīng)用場景,Servlet是JavaWeb開發(fā)的基礎(chǔ),而SpringMVC是一個(gè)基于Servlet的高級(jí)框架,提供了更強(qiáng)大的功能和易用性,文章通過定義、原理和示例代碼,幫助讀者理解這兩個(gè)技術(shù)的區(qū)別與聯(lián)系2025-01-01
k8s部署的java服務(wù)添加idea調(diào)試參數(shù)的方法
文章介紹了如何在K8S容器中的Java服務(wù)上進(jìn)行遠(yuǎn)程調(diào)試,包括配置Deployment、Service以及本地IDEA的調(diào)試設(shè)置,感興趣的朋友跟隨小編一起看看吧2025-02-02
關(guān)于@Autowired注解爆紅的原因分析及解決過程
這篇文章主要介紹了關(guān)于@Autowired注解爆紅的原因分析及解決過程,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2025-06-06
Spring Boot整合QueryDSL的實(shí)現(xiàn)示例
這篇文章主要介紹了Spring Boot整合QueryDSL的實(shí)現(xiàn)示例,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-09-09
Spring中的底層架構(gòu)核心概念類型轉(zhuǎn)換器詳解
這篇文章主要介紹了Spring中的底層架構(gòu)核心概念類型轉(zhuǎn)換器詳解,本文結(jié)合示例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-12-12
利用Java實(shí)現(xiàn)圖片轉(zhuǎn)化為ASCII圖的示例代碼
本文將詳細(xì)講解如何利用 Java 實(shí)現(xiàn)圖片轉(zhuǎn)化為 ASCII 圖,從項(xiàng)目背景與意義、相關(guān)技術(shù)知識(shí),到系統(tǒng)需求與架構(gòu)設(shè)計(jì),再到詳細(xì)實(shí)現(xiàn)思路、完整代碼和代碼解讀,最后對(duì)項(xiàng)目進(jìn)行總結(jié)與展望,需要的朋友可以參考下2025-03-03

