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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

SpringBoot中oauth2.0学习之服务端配置快速上手

發布時間:2025/3/8 javascript 44 豆豆
生活随笔 收集整理的這篇文章主要介紹了 SpringBoot中oauth2.0学习之服务端配置快速上手 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

現在第三方登錄的例子數見不鮮。其實在這種示例當中,oauth2.0是使用比較多的一種授權登錄的標準。oauth2.0也是從oauth1.0升級過來的。那么關于oauth2.0相關的概念及其原理,大家可以參考這篇文章,這篇文章中會有更詳細的解釋,下來我們直接進入正題。

1.1、gradle依賴

compile('org.springframework.cloud:spring-cloud-starter-oauth2')compile('org.springframework.cloud:spring-cloud-starter-security')

在這里我直接引入的是spring-cloud的依賴項,這種依賴的jar包更全面一些,這里面的核心基礎還是spring-security。這里SpringBoot的版本為2.0.6.REALEASE

1.2、@EnableAuthorizationServer

在這里我著重強調一下這個注解:@EnableAuthorizationServer,這個注解源代碼如下:

@Target(ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)@Documented@Import({AuthorizationServerEndpointsConfiguration.class, AuthorizationServerSecurityConfiguration.class})public @interface EnableAuthorizationServer {}

這個注解主要是導入兩個配置類,分別是:

  • AuthorizationServerEndpointsConfiguration,這個配置類主要配置授權端點,獲取token的端點。大家就把對應的端點想象成controller即可,在這個controller下開放了若干個@RequestMapping,比如常見的有:/oauth/authorize(授權路徑),/oauth/token(獲取token)等
  • AuthorizationServerSecurityConfiguration,主要是做spring-security的安全配置,我們可以看一下相關代碼:
public class AuthorizationServerSecurityConfiguration extends WebSecurityConfigurerAdapter {@Autowiredprivate List<AuthorizationServerConfigurer> configurers = Collections.emptyList();@Autowiredprivate ClientDetailsService clientDetailsService;@Autowiredprivate AuthorizationServerEndpointsConfiguration endpoints;@Autowiredpublic void configure(ClientDetailsServiceConfigurer clientDetails) throws Exception {for (AuthorizationServerConfigurer configurer : configurers) {configurer.configure(clientDetails);}}@Overrideprotected void configure(AuthenticationManagerBuilder auth) throws Exception {// Over-riding to make sure this.disableLocalConfigureAuthenticationBldr = false// This will ensure that when this configurer builds the AuthenticationManager it will not attempt// to find another 'Global' AuthenticationManager in the ApplicationContext (if available),// and set that as the parent of this 'Local' AuthenticationManager.// This AuthenticationManager should only be wired up with an AuthenticationProvider// composed of the ClientDetailsService (wired in this configuration) for authenticating 'clients' only.}@Overrideprotected void configure(HttpSecurity http) throws Exception {//....省略部分代碼String tokenEndpointPath = handlerMapping.getServletPath("/oauth/token");String tokenKeyPath = handlerMapping.getServletPath("/oauth/token_key");String checkTokenPath = handlerMapping.getServletPath("/oauth/check_token");if (!endpoints.getEndpointsConfigurer().isUserDetailsServiceOverride()) {UserDetailsService userDetailsService = http.getSharedObject(UserDetailsService.class);endpoints.getEndpointsConfigurer().userDetailsService(userDetailsService);}// @formatter:off//上述節點的請求需要授權驗證http.authorizeRequests().antMatchers(tokenEndpointPath).fullyAuthenticated().antMatchers(tokenKeyPath).access(configurer.getTokenKeyAccess()).antMatchers(checkTokenPath).access(configurer.getCheckTokenAccess()).and().requestMatchers().antMatchers(tokenEndpointPath, tokenKeyPath, checkTokenPath).and().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.NEVER);// @formatter:onhttp.setSharedObject(ClientDetailsService.class, clientDetailsService);}protected void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception {for (AuthorizationServerConfigurer configurer : configurers) {configurer.configure(oauthServer);}}}

1.2.1、AuthorizationServerConfigurer

這個接口是認證授權配置的核心接口,不過既然是SpringBoot我們就先來看看它怎么幫我們裝配的,我們可以在org.springframework.boot.autoconfigure.security.oauth2.authserver這個包下面找到對應配置的Bean:

@Configuration@ConditionalOnClass(EnableAuthorizationServer.class)@ConditionalOnMissingBean(AuthorizationServerConfigurer.class)@ConditionalOnBean(AuthorizationServerEndpointsConfiguration.class)@EnableConfigurationProperties(AuthorizationServerProperties.class)public class OAuth2AuthorizationServerConfigurationextends AuthorizationServerConfigurerAdapter {//....@Overridepublic void configure(ClientDetailsServiceConfigurer clients) throws Exception {//默認基于內存創建ClientDetailsClientDetailsServiceBuilder<InMemoryClientDetailsServiceBuilder>.ClientBuilder builder = clients.inMemory().withClient(this.details.getClientId());builder.secret(this.details.getClientSecret()).resourceIds(this.details.getResourceIds().toArray(new String[0])).authorizedGrantTypes(this.details.getAuthorizedGrantTypes().toArray(new String[0])).authorities(AuthorityUtils.authorityListToSet(this.details.getAuthorities()).toArray(new String[0])).scopes(this.details.getScope().toArray(new String[0]));if (this.details.getAutoApproveScopes() != null) {builder.autoApprove(this.details.getAutoApproveScopes().toArray(new String[0]));}if (this.details.getAccessTokenValiditySeconds() != null) {builder.accessTokenValiditySeconds(this.details.getAccessTokenValiditySeconds());}if (this.details.getRefreshTokenValiditySeconds() != null) {builder.refreshTokenValiditySeconds(this.details.getRefreshTokenValiditySeconds());}if (this.details.getRegisteredRedirectUri() != null) {builder.redirectUris(this.details.getRegisteredRedirectUri().toArray(new String[0]));}}@Overridepublic void configure(AuthorizationServerEndpointsConfigurer endpoints)throws Exception {if (this.tokenConverter != null) {endpoints.accessTokenConverter(this.tokenConverter);}if (this.tokenStore != null) {endpoints.tokenStore(this.tokenStore);}if (this.details.getAuthorizedGrantTypes().contains("password")) {endpoints.authenticationManager(this.authenticationManager);}}@Overridepublic void configure(AuthorizationServerSecurityConfigurer security)throws Exception {security.passwordEncoder(NoOpPasswordEncoder.getInstance());if (this.properties.getCheckTokenAccess() != null) {security.checkTokenAccess(this.properties.getCheckTokenAccess());}if (this.properties.getTokenKeyAccess() != null) {security.tokenKeyAccess(this.properties.getTokenKeyAccess());}if (this.properties.getRealm() != null) {security.realm(this.properties.getRealm());}}@Configuration@ConditionalOnMissingBean(BaseClientDetails.class)protected static class BaseClientDetailsConfiguration {private final OAuth2ClientProperties client;protected BaseClientDetailsConfiguration(OAuth2ClientProperties client) {this.client = client;}/**由此可知它會尋找security.oauth2.client的配置*/@Bean@ConfigurationProperties(prefix = "security.oauth2.client")public BaseClientDetails oauth2ClientDetails() {BaseClientDetails details = new BaseClientDetails();if (this.client.getClientId() == null) {this.client.setClientId(UUID.randomUUID().toString());}details.setClientId(this.client.getClientId());details.setClientSecret(this.client.getClientSecret());details.setAuthorizedGrantTypes(Arrays.asList("authorization_code","password", "client_credentials", "implicit", "refresh_token"));details.setAuthorities(AuthorityUtils.commaSeparatedStringToAuthorityList("ROLE_USER"));details.setRegisteredRedirectUri(Collections.<String>emptySet());return details;}}}

如果沒有用spring-boot的用戶,可以也可以參考上述的配置方法,自行配置

1.3、application.yml的配置

根據上述代碼我們可以知道,springboot通過外部化配置的security.oauth2.client的前綴來配置客戶端。那么因此我們不妨在外部化配置文件里做如下配置:

server:port: 8080security:oauth2:client:client-id: rootclient-secret: rootscope:- email- username- facespring:security:user:name: rootpassword: rootroles: ADMIN

這里先做最基本的配置,配置client-id,client-secret,scope。特別注意oauth2.0一定要先經過springsecurity的auth認證,因此需要在這里配置一個內存用戶名與密碼為root與root

1.4、配置資源服務器

通過資源服務器來保護我們指定的資源,必須在獲取授權認證的時候才能訪問。在SpringBoot當中,我們可以通過@EnableResourceServer注解來開啟此功能。該注解定義如下:

@Target(ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)@Documented@Import(ResourceServerConfiguration.class)public @interface EnableResourceServer {}

我們可以看到這個注解導入了默認的資源配置信息:ResourceServerConfiguration,它的源代碼如下:

@Configurationpublic class ResourceServerConfiguration extends WebSecurityConfigurerAdapter implements Ordered {//....@Overrideprotected void configure(HttpSecurity http) throws Exception {ResourceServerSecurityConfigurer resources = new ResourceServerSecurityConfigurer();ResourceServerTokenServices services = resolveTokenServices();if (services != null) {resources.tokenServices(services);}else {if (tokenStore != null) {resources.tokenStore(tokenStore);}else if (endpoints != null) {resources.tokenStore(endpoints.getEndpointsConfigurer().getTokenStore());}}if (eventPublisher != null) {resources.eventPublisher(eventPublisher);}//配置資源for (ResourceServerConfigurer configurer : configurers) {configurer.configure(resources);}// @formatter:offhttp.authenticationProvider(new AnonymousAuthenticationProvider("default"))// N.B. exceptionHandling is duplicated in resources.configure() so that// it works.exceptionHandling().accessDeniedHandler(resources.getAccessDeniedHandler()).and().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and().csrf().disable();// @formatter:onhttp.apply(resources);if (endpoints != null) {// Assume we are in an Authorization Serverhttp.requestMatcher(new NotOAuthRequestMatcher(endpoints.oauth2EndpointHandlerMapping()));}for (ResourceServerConfigurer configurer : configurers) {// Delegates can add authorizeRequests() hereconfigurer.configure(http);}//如果沒有任何配置資源,則所有請求保護if (configurers.isEmpty()) {// Add anyRequest() last as a fall back. Spring Security would// replace an existing anyRequest() matcher with this one, so to// avoid that we only add it if the user hasn't configured anything.http.authorizeRequests().anyRequest().authenticated();}}//....}

在這里主要是配置資源服務器的配置,我們可以得到如下幾點信息:

  • 資源配置的核心ResourceServerConfigurer,在這里如果沒有任何配置,則所有請求都要進行token認證
  • TokenStore 主要定義了對token的增刪改查操作,用于持久化token
  • ResourceServerTokenServices 資源服務的service(服務層),這里主要還是根據token來拿到OAuth2Authentication與OAuth2AccessToken

1.5、完整示例

1.5.1、資源認證配置

@Configuration@EnableResourceServerpublic class ResourceConfigure extends ResourceServerConfigurerAdapter {@Overridepublic void configure(HttpSecurity http) throws Exception {http.csrf().disable().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED).and().authorizeRequests().antMatchers("/free/**").permitAll().and().authorizeRequests().anyRequest().authenticated().and().formLogin().permitAll();//必須認證過后才可以訪問}}

在這里如果以/free/**請求路徑的,都允許直接訪問。否則,都必須攜帶access_token才能訪問。

1.5.2 、授權認證配置

@Configurationpublic class WebSecurityConfig extends WebSecurityConfigurerAdapter {@Overrideprotected void configure(HttpSecurity http) throws Exception {http.csrf().disable().requestMatchers().anyRequest().and().authorizeRequests().antMatchers("/oauth/*").authenticated().and().formLogin().permitAll();}}

根據上文所述,AuthorizationServerEndpoint與TokenEndpoint會開放/oauth/authorize與/oauth/token端點,因此我們必須保證訪問端點進行授權認證前,通過springsecurity的用戶認證,因此在這里配置了/oauth/*

1.5.3、啟動類

@SpringBootApplication@EnableAuthorizationServer@Controllerpublic class AuthorizationServer {@GetMapping("/order")public ResponseEntity<String> order() {ResponseEntity<String> responseEntity = new ResponseEntity("order", HttpStatus.OK);return responseEntity;}@GetMapping("/free/test")public ResponseEntity<String> test() {ResponseEntity<String> responseEntity = new ResponseEntity("free", HttpStatus.OK);return responseEntity;}public static void main(String[] args) {SpringApplication.run(AuthorizationServer.class, args);}}

1.5.4、訪問請求

首先我們通過postman 訪問http://localhost:8080/order會得到如下界面:

此時我們明顯可以看到對應的資源需要攜帶有效的token才可以訪問,那么我們此時要在postman的Authorization進行oauth2.0配置認證。截圖如下:

在這里點擊Get New Access Token 來從認證服務器獲取token,點擊后配置如下:

`

  • scope配置對應application.yml中的配置信息,這里面可以放置用戶的屬性信息,比如說昵稱 頭像 電話等等
  • State代表狀態碼,設置一個State標志
  • 回調地址這里必須配置,通過這個地址當同意授權后會返回一個認證的code給我們,我們根據這個code請求token
  • 認證地址與獲取token的地址請填寫,相關Endpoint生成的地址

當經過一連串認證后,我們即可拿到token:


當我們獲取到最新的token以后,我們即可訪問到對應的請求資源:

總結

以上是生活随笔為你收集整理的SpringBoot中oauth2.0学习之服务端配置快速上手的全部內容,希望文章能夠幫你解決所遇到的問題。

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