溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

Springboot開發(fā)OAuth2認(rèn)證授權(quán)與資源服務(wù)器的方法

發(fā)布時(shí)間:2021-06-22 13:34:56 來源:億速云 閱讀:420 作者:chen 欄目:開發(fā)技術(shù)

這篇文章主要講解了“Springboot開發(fā)OAuth2認(rèn)證授權(quán)與資源服務(wù)器的方法”,文中的講解內(nèi)容簡單清晰,易于學(xué)習(xí)與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學(xué)習(xí)“Springboot開發(fā)OAuth2認(rèn)證授權(quán)與資源服務(wù)器的方法”吧!

設(shè)計(jì)并開發(fā)一個(gè)開放平臺(tái)。

一、設(shè)計(jì):

Springboot開發(fā)OAuth2認(rèn)證授權(quán)與資源服務(wù)器的方法

網(wǎng)關(guān)可以 與認(rèn)證授權(quán)服務(wù)合在一起,也可以分開。

二、開發(fā)與實(shí)現(xiàn):

用Oauth3技術(shù)對訪問受保護(hù)的資源的客戶端進(jìn)行認(rèn)證與授權(quán)。

Oauth3技術(shù)應(yīng)用的關(guān)鍵是:

1)服務(wù)器對OAuth3客戶端進(jìn)行認(rèn)證與授權(quán)。

2)Token的發(fā)放。

3)通過access_token訪問受OAuth3保護(hù)的資源。

選用的關(guān)鍵技術(shù):Springboot, Spring-security, Spring-security-oauth3。

提供一個(gè)簡化版,用戶、token數(shù)據(jù)保存在內(nèi)存中,用戶與客戶端的認(rèn)證授權(quán)服務(wù)、資源服務(wù),都是在同一個(gè)工程中?,F(xiàn)實(shí)項(xiàng)目中,技術(shù)架構(gòu)通常上將用戶與客戶端的認(rèn)證授權(quán)服務(wù)設(shè)計(jì)在一個(gè)子系統(tǒng)(工程)中,而資源服務(wù)設(shè)計(jì)為另一個(gè)子系統(tǒng)(工程)。

1、Spring-security對用戶身份進(jìn)行認(rèn)證授權(quán):

主要作用是對用戶身份通過用戶名與密碼的方式進(jìn)行認(rèn)證并且授權(quán)。

package com.banling.oauth3server.config; 
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
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.web.util.matcher.AntPathRequestMatcher; 
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter{
	
	@Autowired
    public void globalUserDetails(AuthenticationManagerBuilder auth) throws Exception {
    	//用戶信息保存在內(nèi)存中
		//在鑒定角色roler時(shí),會(huì)默認(rèn)加上ROLLER_前綴
        auth.inMemoryAuthentication().withUser("user").password("user").roles("USER").and()
        	.withUser("test").password("test").roles("TEST");
    }
	
	@Override
    protected void configure(HttpSecurity http) throws Exception {
		http.formLogin() //登記界面,默認(rèn)是permit All
		.and()
		.authorizeRequests().antMatchers("/","/home").permitAll() //不用身份認(rèn)證可以訪問
		.and()
		.authorizeRequests().anyRequest().authenticated() //其它的請求要求必須有身份認(rèn)證
        .and()
        .csrf() //防止CSRF(跨站請求偽造)配置
        .requireCsrfProtectionMatcher(new AntPathRequestMatcher("/oauth/authorize")).disable();
    }
	
	@Override
    @Bean
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }
}

配置用戶信息,保存在內(nèi)存中。也可以自定義將用戶數(shù)據(jù)保存在數(shù)據(jù)庫中,實(shí)現(xiàn)UserDetailsService接口,進(jìn)行認(rèn)證與授權(quán),略。

配置訪問哪些URL需要授權(quán)。必須配置authorizeRequests(),否則啟動(dòng)報(bào)錯(cuò),說是沒有啟用security技術(shù)。

注意,在這里的身份進(jìn)行認(rèn)證與授權(quán)沒有涉及到OAuth的技術(shù):

當(dāng)訪問要授權(quán)的URL時(shí),請求會(huì)被DelegatingFilterProxy攔截,如果還沒有授權(quán),請求就會(huì)被重定向到登錄界面。在登錄成功(身份認(rèn)證并授權(quán))后,請求被重定向至之前訪問的URL。

2、OAuth3的授權(quán)服務(wù):

主要作用是OAuth3的客戶端進(jìn)行認(rèn)證與授權(quán)。

package com.banling.oauth3server.config; 
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.oauth3.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth3.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth3.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth3.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth3.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
import org.springframework.security.oauth3.provider.approval.ApprovalStore;
import org.springframework.security.oauth3.provider.approval.TokenApprovalStore;
import org.springframework.security.oauth3.provider.token.TokenStore;
import org.springframework.security.oauth3.provider.token.store.InMemoryTokenStore; 
@Configuration
@EnableAuthorizationServer
public class AuthServerConfig extends AuthorizationServerConfigurerAdapter{
	
	@Autowired
	private TokenStore tokenStore;
	
	@Autowired
    private AuthenticationManager authenticationManager;
	
	@Autowired
	private ApprovalStore approvalStore;
	
	@Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        //添加客戶端信息
        //使用內(nèi)存存儲(chǔ)OAuth客戶端信息
        clients.inMemory()
                // client_id
                .withClient("client")
                // client_secret
                .secret("secret")
                // 該client允許的授權(quán)類型,不同的類型,則獲得token的方式不一樣。
                .authorizedGrantTypes("authorization_code","implicit","refresh_token")
                .resourceIds("resourceId")
                //回調(diào)uri,在authorization_code與implicit授權(quán)方式時(shí),用以接收服務(wù)器的返回信息
                .redirectUris("http://localhost:8090/")
                // 允許的授權(quán)范圍
                .scopes("app","test");
    }
	
	@Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
		//reuseRefreshTokens設(shè)置為false時(shí),每次通過refresh_token獲得access_token時(shí),也會(huì)刷新refresh_token;也就是說,會(huì)返回全新的access_token與refresh_token。
		//默認(rèn)值是true,只返回新的access_token,refresh_token不變。
        endpoints.tokenStore(tokenStore).approvalStore(approvalStore).reuseRefreshTokens(false)
                .authenticationManager(authenticationManager);
    }
	
	@Override
    public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
        security.realm("OAuth3-Sample")
        	.allowFormAuthenticationForClients()
        	.tokenKeyAccess("permitAll()")
        	.checkTokenAccess("isAuthenticated()");
    }
	
	@Bean
	public TokenStore tokenStore() {
		//token保存在內(nèi)存中(也可以保存在數(shù)據(jù)庫、Redis中)。
		//如果保存在中間件(數(shù)據(jù)庫、Redis),那么資源服務(wù)器與認(rèn)證服務(wù)器可以不在同一個(gè)工程中。
		//注意:如果不保存access_token,則沒法通過access_token取得用戶信息
		return new InMemoryTokenStore();
	}
	
	@Bean
	public ApprovalStore approvalStore() throws Exception {
		TokenApprovalStore store = new TokenApprovalStore();
		store.setTokenStore(tokenStore);
		return store;
	}
}

配置OAuth3的客戶端信息:clientId、client_secret、authorization_type、redirect_url等。本例是將數(shù)據(jù)保存在內(nèi)存中。也可以保存在數(shù)據(jù)庫中,實(shí)現(xiàn)ClientDetailsService接口,進(jìn)行認(rèn)證與授權(quán),略。

TokenStore是access_token的存儲(chǔ)單元,可以保存在內(nèi)存、數(shù)據(jù)庫、Redis中。本例是保存在內(nèi)存中。

3、OAuth3的資源服務(wù):

主要作用是配置資源受保護(hù)的OAuth3策略。

package com.banling.oauth3server.config; 
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.oauth3.config.annotation.web.configuration.EnableResourceServer;
import org.springframework.security.oauth3.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
import org.springframework.security.oauth3.config.annotation.web.configurers.ResourceServerSecurityConfigurer;
import org.springframework.security.oauth3.provider.token.TokenStore; 
@Configuration
@EnableResourceServer
public class ResServerConfig extends ResourceServerConfigurerAdapter{
	
	@Autowired
	private TokenStore tokenStore;
 
	@Override
    public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
        resources
                .tokenStore(tokenStore)
                .resourceId("resourceId");
    }
 
    @Override
    public void configure(HttpSecurity http) throws Exception {	    	
    	/*
    	 注意:
    	 1、必須先加上: .requestMatchers().antMatchers(...),表示對資源進(jìn)行保護(hù),也就是說,在訪問前要進(jìn)行OAuth認(rèn)證。
    	 2、接著:訪問受保護(hù)的資源時(shí),要具有哪里權(quán)限。
    	 ------------------------------------
    	 否則,請求只是被Security的攔截器攔截,請求根本到不了OAuth3的攔截器。
    	 同時(shí),還要注意先配置:security.oauth3.resource.filter-order=3,否則通過access_token取不到用戶信息。
    	 ------------------------------------
    	 requestMatchers()部分說明:
    	 Invoking requestMatchers() will not override previous invocations of ::
    	 mvcMatcher(String)}, requestMatchers(), antMatcher(String), regexMatcher(String), and requestMatcher(RequestMatcher).
    	 */
        
        http
        	// Since we want the protected resources to be accessible in the UI as well we need 
			// session creation to be allowed (it's disabled by default in 2.0.6)
        	//另外,如果不設(shè)置,那么在通過瀏覽器訪問被保護(hù)的任何資源時(shí),每次是不同的SessionID,并且將每次請求的歷史都記錄在OAuth3Authentication的details的中
			.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED)
			.and()
       		.requestMatchers()
           .antMatchers("/user","/res/**")
           .and()
           .authorizeRequests()
           .antMatchers("/user","/res/**")
           .authenticated();
    }
}

配置哪些URL資源是受OAuth3保護(hù)的。注意,必須配置sessionManagement(),否則訪問受護(hù)資源請求不會(huì)被OAuth3的攔截器ClientCredentialsTokenEndpointFilter與OAuth3AuthenticationProcessingFilter攔截,也就是說,沒有配置的話,資源沒有受到OAuth3的保護(hù)。

4、受OAuth3保存的資源:

1)獲取OAuth3客戶端的信息

package com.banling.oauth3server.web; 
import java.security.Principal; 
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
 
@RestController
public class UserController {
 
	@RequestMapping("/user")
	public Principal user(Principal principal) {
		//principal在經(jīng)過security攔截后,是org.springframework.security.authentication.UsernamePasswordAuthenticationToken
		//在經(jīng)OAuth3攔截后,是OAuth3Authentication
	    return principal;
	}	
}

2)其它受保護(hù)的資源

package com.banling.oauth3server.web;
import java.security.Principal; 
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
 
/**
 * 作為OAuth3的資源服務(wù)時(shí),不能在Controller(或者RestController)注解上寫上URL,因?yàn)檫@樣不會(huì)被識(shí)別,會(huì)報(bào)404錯(cuò)誤。<br>
 *<br> {
 *<br>     "timestamp": 1544580859138,
 *<br>     "status": 404,
 *<br>     "error": "Not Found",
 *<br>     "message": "No message available",
 *<br>     "path": "/res/getMsg"
 *<br> }
 *<br>
 *
 *
 */
@RestController()//作為資源服務(wù)時(shí),不能帶上url,@RestController("/res")是錯(cuò)的,無法識(shí)別。只能在方法上注解全路徑
public class ResController {
	
	@RequestMapping("/res/getMsg")
	public String getMsg(String msg,Principal principal) {//principal中封裝了客戶端(用戶,也就是clientDetails,區(qū)別于Security的UserDetails,其實(shí)clientDetails中也封裝了UserDetails),不是必須的參數(shù),除非你想得到用戶信息,才加上principal。
		return "Get the msg: "+msg;
	}
}

5、application.properties配置:

security.oauth3.resource.filter-order=3 必須配置,否則對受護(hù)資源請求不會(huì)被OAuth3的攔截器攔截。

6、測試

1)authorization_code方式獲取code,然后再通過code獲取access_token(和refresh_token)。

在瀏覽輸入:

http://localhost:8080/oauth/authorize?client_id=client&response_type=code&redirect_uri=http://localhost:8090/

在登錄界面輸入用戶名與密碼user/user,提交。

提交后服務(wù)重定向 至scope的授權(quán)界面:

Springboot開發(fā)OAuth2認(rèn)證授權(quán)與資源服務(wù)器的方法

授權(quán)后,在回調(diào)uri中可以得從code:

Springboot開發(fā)OAuth2認(rèn)證授權(quán)與資源服務(wù)器的方法

用postman工具,設(shè)置header的值,通過code獲取access_token與fresh_token:

Springboot開發(fā)OAuth2認(rèn)證授權(quán)與資源服務(wù)器的方法

2)implict方式接獲取access_token。

瀏覽器中輸入:

http://localhost:8080/oauth/authorize?client_id=client&response_type=token&redirect_uri=http://localhost:8090/

可以直接獲得access_token。

Springboot開發(fā)OAuth2認(rèn)證授權(quán)與資源服務(wù)器的方法

3)通過refresh_token獲取access_token與refresh_token。

用postman工具測試,根據(jù)refresh_token獲取新的access_token與fresh_token。

Springboot開發(fā)OAuth2認(rèn)證授權(quán)與資源服務(wù)器的方法

4)獲取OAuth3客戶端的信息。

可以通過get方式,也可以通過設(shè)置header獲取。

get方式,看url字符串:

Springboot開發(fā)OAuth2認(rèn)證授權(quán)與資源服務(wù)器的方法

設(shè)置header的方式:

Springboot開發(fā)OAuth2認(rèn)證授權(quán)與資源服務(wù)器的方法

5)訪問其它受保護(hù)的資源

Springboot開發(fā)OAuth2認(rèn)證授權(quán)與資源服務(wù)器的方法

github上的源碼: https://github.com/banat020/OAuth3-server

感謝各位的閱讀,以上就是“Springboot開發(fā)OAuth2認(rèn)證授權(quán)與資源服務(wù)器的方法”的內(nèi)容了,經(jīng)過本文的學(xué)習(xí)后,相信大家對Springboot開發(fā)OAuth2認(rèn)證授權(quán)與資源服務(wù)器的方法這一問題有了更深刻的體會(huì),具體使用情況還需要大家實(shí)踐驗(yàn)證。這里是億速云,小編將為大家推送更多相關(guān)知識(shí)點(diǎn)的文章,歡迎關(guān)注!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI