当前位置:首页 > 行业发展 > 正文

Spring Authorization Server 授权服务器

说明SpringAuthorizationServer遵循和,它建立在SpringSecurity之上。最小化项目创建项目要求JDK11以上使用Idea创建一个Maven的SpringBoot(笔者使用的是)项目pom需要引入AuthorizationServer的配置/groupIdartifac...

说明SpringAuthorizationServer遵循和,它建立在SpringSecurity之上。最小化项目创建项目要求JDK11以上使用Idea创建一个Maven的SpringBoot(笔者使......

说明

SpringAuthorizationServer遵循和,它建立在SpringSecurity之上。

最小化项目创建项目

要求JDK11以上

使用Idea创建一个Maven的SpringBoot(笔者使用的是)项目

pom需要引入AuthorizationServer的配置

/groupIdartifactIdspring-security-oauth2-authorization-server//version/depency复制代码

完整的文件如下:

?xmlversion="1.0"encoding="UTF-8"?projectxmlns=""xmlns:xsi=""xsi:schemaLocation=""//groupIdartifactIdspring-boot-starter-parent//versionrelativePath/!--lookupparentfromrepository--//groupIdartifactIdSpring_Authorization_Server_0_3_x//////propertiesdepencies!--必须引入--/groupIdartifactIdspring-security-oauth2-authorization-server//version/depency!--必须引入--/groupIdartifactIdspring-boot-starter-web/artifactId/depency!--可选引入--/groupIdartifactIdspring-boot-starter-actuator/artifactId/depency!--可选引入--/groupIdartifactIdspring-boot-starter-test/artifactIdscopetest/scope/depency//groupIdartifactIdspring-boot-maven-plugin/artifactId/plugin/plugins/build/project复制代码
配置

使用@Bean和@Configuration创建配置,这是官方推荐的最小配置。

至此最小化项目完成,这就能够完成oauth2的授权。

测试授权码模式

浏览器访问;client_id=messaging-clientscope=_uri=

输入用户名(user)密码(password)后

提交后,会自动跳转到redirect_uri地址,并且地址会紧跟着code。

返回的code是

axia5-kuIIzO1D1eu1V_02KawWIkRydiZrDEPAtLhNlYC7kLeUazD_bh5UXGQVJj7W2gxC1zpQJuQ2D9ZVrQyVfufxMYyv4fkjjMitiQ1gH-bGQ6KqGy5egeC15NfHBt复制代码

接下来需要使用这个code获取token(我用postman请求)。

获取token

授权码获取token的请求地址是oauth2/token,post请求:

上线这个三个参数是必须的,并且要跟代码中设置完全一直,另外获取token要传递client_id和client_secret参数,默认不支持使用表单传递,要通过header传递。比如在postman中

其实上线的操作实际上就是在header中传递了一个header,key=Authorization,value是client_id:client_secret,然后使用base64加密的字符串,然后前面加上Basic(注意后面有空格)。对于我这个例子来说就是BasicbWVzc2FnaW5nLWNsaWVudDpzZWNyZXQ=

返回结果是:

{"access_token":"eyJraWQiOiIxNGMxO1NDMyMzg0OSwic2NvcGUiOlsibWVzc2FnZS5yZWFkIl0sImlzcyI6Imh0dHA6XC9cLzEyN_KRC2SnOH93nGYnoP2uWZwyiamke5PGWa72OHPxgwktgAxK0gHIjQ_sgh5tD4R2swb9bARIn2ZvUb3DtIXpLzEoCGRu4DqJoaUFnj71oAvX1MSruHeLqQaCwL2nJ-C-TNwj_mFHzcZFdaFZRQIIIkaG46Zgj1G0BCxpKtJy3FVIcbGJK-HYHHdh2XOMAIyCA5MrDn2VtZmJDwSbhSSEdU8jY8n41LPUd79koozIH_6onrx-y9ly3-evV3cAGBvsWA26h6PAR0Nxv47LXaUM5Hn_6OA20noCi53CC0qdahRJSs9eHpXsLd0rpjPDrk4nK9S7G0wTIlw","refresh_token":"2CvlhRXdg6EK0ZzS_3kI-AI-AeCXBFpvD1krSbu28sTundjXnwvZT4AuQ03rtUr5TD2VFUWyuAJ68fAmNIonUVSRaDKzdx-Z2Z61np_HlcBF2iUxLRyl4JW9jeBQ7CZG","scope":"","token_type":"Bearer","expires_in":299}复制代码
刷新token

结果是:

{"access_token":"eyJraWQiOiIxNGMxO1NDMyNDU1OCwic2NvcGUiOlsibWVzc2FnZS5yZWFkIl0sImlzcyI6Imh0dHA6XC9cLzEyN1hhjpl1d59RixOXkOAIK6PUI_-y_6MTmXL71YZ1lmrifhZ24bYkqXQKMAsbFvj3bXn6RyVnTwFsiy9IzZBRK_-PTPWQd9DbaYkmpryeZtGBqUFYAyBDrgCTYgw0SEoDI2qEX_W3Bgxiz9yTDH5Gszdbe0CzxvHP7LOGDi7-q-WziGhQCoMfFMK0P2WvzeAagseUEUpoSJTk8IMh-_8EgatrwilSYjkKKwgf_-hd9UXDi4bsW9MNA9iIDCYqKJ5dflTutoUJX8oxpnYTwP8iGNDA","refresh_token":"2CvlhRXdg6EK0ZzS_3kI-AI-AeCXBFpvD1krSbu28sTundjXnwvZT4AuQ03rtUr5TD2VFUWyuAJ68fAmNIonUVSRaDKzdx-Z2Z61np_HlcBF2iUxLRyl4JW9jeBQ7CZG","scope":"","token_type":"Bearer","expires_in":299}复制代码
简化模式

在中被移除

客户端模式获取token

结果是:

{"access_token":"eyJraWQiOiIxNGMxOudCIsIm5iZiI6MTY1NDMyNDc5Nywic2NvcGUiOlsib3BlbmlkIiwibWVzc2FnZS5yZWFkIiwibWVzc2FnZS53cml0ZSJdLCJpc3MiOiJodHRwOlwvXC8xMjc_b9m3rd9-QqkQpuxbFBD_o4dk3wl7PKVlZuWNCVrcvEXMFREexU6wwKtzTWKTBWYtDOAvKJN81iJ34UqsXRQ_M3xvUlpVXMjFKY9c3hsP9te8FpfcMi4IZfnHS79CunTh7tgovEo53nu9UNQ2qKy_MR9a13cXpe_AepOP_68gaLO-SAdRI-H9L4e57Y3w7Lq-UWUxywtnAtEcnm_PTGaA-gIEvCiN0rx6pZFBOxv-58OhNfp79oTN33yBDN-E3dSWgioQDp-Sc7kIb8z-rzXa1ZQgx19xTGg","scope":"","token_type":"Bearer","expires_in":299}复制代码

客户端模式没有刷新token模式。

密码模式

在中被移除

配置默认配置

之前已经通过最小配置,完成了一个SpringAuthorizationServer项目,本章学习下关于配置的内容。

SpringAuthorizationServer还提供了一种实现最小配置的默认配置形式。就是通过OAuth2AuthorizationServerConfiguration这个类。

看下这个类的源码:

/**Copyright2020-2021theoriginalauthororauthors.**LicensedundertheApacheLicense,(the"License");*youmaynotusethisfileexceptincompliancewiththeLicense.*YoumayobtainacopyoftheLicenseat****Unlessrequiredbyapplicablelaworagreedtoinwriting,software*distributedundertheLicenseisdistributedonan"ASIS"BASIS,*WITHOUTWARRANTIESORCONDITIONSOFANYKIND,eitherexpressorimplied.*SeetheLicenseforthespecificlanguagegoverningpermissionsand*limitationsundertheLicense.*/;;;;;;;;;;;;;;;;;;;;;/***{@linkConfiguration}**@authorJoeGrandja*@*@seeOAuth2AuthorizationServerConfigurer*/@Configuration(proxyBeanMethods=false)publicclassOAuth2AuthorizationServerConfiguration{@Bean@Order(_PRECEDENCE)publicSecurityFilterChainauthorizationServerSecurityFilterChain(HttpSecurityhttp)throwsException{applyDefaultSecurity(http);();}//@formatter:offpublicstaticvoidapplyDefaultSecurity(HttpSecurityhttp)throwsException{OAuth2AuthorizationServerConfigurerHttpSecurityauthorizationServerConfigurer=newOAuth2AuthorizationServerConfigurer();RequestMatcherpointsMatcher=();(pointsMatcher).authorizeRequests(().authenticated()).csrf((pointsMatcher)).apply(authorizationServerConfigurer);}//@formatter:onpublicstaticJwtDecoderjwtDecoder(JWKSourceSecurityContextjwkSource){SetJWSAlgorithmjwsAlgs=newHashSet();();();(_SHA);ConfigurableJWTProcessorSecurityContextjwtProcessor=newDefaultJWTProcessor();JWSKeySelectorSecurityContextjwsKeySelector=newJWSVerificationKeySelector(jwsAlgs,jwkSource);(jwsKeySelector);//OverridethedefaultNimbus((claims,context)-{});returnnewNimbusJwtDecoder(jwtProcessor);}@BeanRegisterMissingBeanPostProcessorregisterMissingBeanPostProcessor(){RegisterMissingBeanPostProcessorpostProcessor=newRegisterMissingBeanPostProcessor();(,()-().build());returnpostProcessor;}}复制代码

这里注入一个叫做authorizationServerSecurityFilterChain的bean,这跟我之前最小化项目时实现的基本是相同的。

有了这个bean,就会支持如下协议端点:

OAuth2Authorizationpoint

OAuth2Tokenpoint

OAuth2TokenIntrospectionpoint

OAuth2TokenRevocationpoint

OAuth2AuthorizationServerMetadatapoint

JWKSetpoint

接来我我尝试使用OAuth2AuthorizationServerConfiguration这个类来实现一个AuthorizationServer。

SpringSecurity使用SecurityConfig类,创建一个新的AuthorizationServer配置类AuthorizationServerConfig。

SecurityConfig类配置如下:

代码如下:

;;;;;;;;;;;;;;;;;;;;;;@Configuration@Import()publicclassAuthorizationServerConfig{/***oauth2用于第三方认证,RegisteredClientRepository主要用于管理第三方(每个第三方就是一个客户端)**@return*/@BeanpublicRegisteredClientRepositoryregisteredClientRepository(){RegisteredClientregisteredClient=(().toString()).clientId("messaging-client").clientSecret("{noop}secret").clientAuthenticationMethod(_SECRET_BASIC).authorizationGrantType(_CODE).authorizationGrantType(_TOKEN).authorizationGrantType(_CREDENTIALS).redirectUri("").redirectUri("").scope().scope("").scope("").clientSettings(().requireAuthorizationConsent(true).build()).build();returnnewInMemoryRegisteredClientRepository(registeredClient);}/***用于给access_token签名使用。**@return*/@BeanpublicJWKSourceSecurityContextjwkSource(){KeyPairkeyPair=generateRsaKey();RSAPublicKeypublicKey=(RSAPublicKey)();RSAPrivateKeyprivateKey=(RSAPrivateKey)();RSAKeyrsaKey=(publicKey).privateKey(privateKey).keyID(().toString()).build();JWKSetjwkSet=newJWKSet(rsaKey);returnnewImmutableJWKSet(jwkSet);}/***生成秘钥对,为jwkSource提供服务。**@return*/privatestaticKeyPairgenerateRsaKey(){KeyPairkeyPair;try{KeyPairGeneratorkeyPairGenerator=("RSA");(2048);keyPair=();}catch(Exceptionex){thrownewIllegalStateException(ex);}returnkeyPair;}}复制代码

至此可以实现了AuthorizationServer。

测试客户端调用。

授权码模式测试

授权码模式也没有问题。

存储配置

SpringAuthorizationServer默认是支持内存和JDBC两种存储模式的,内存模式只适合开发和简单的测试。接下来我们来实现JDBC存储方式。

修改步骤如下:

引入JDBC相关依赖。

创建数据库并初始化表,以及在文件中配置数据库连接。

修改SpringSecurity和SpringauthorizationServer的配置。

初始化表数据

测试服务

接下来我依次实现。

引入JDBC相关依赖

/groupIdartifactIdspring-boot-starter-jdbc/artifactId//groupIdartifactIdpostgresql/artifactIdscoperuntime/scope/depency复制代码

创建数据库并初始化表,以及在文件中配置数据库连接。

createtableoauth2_authorization(idvarchar(100)notnullprimarykey,registered_client_idvarchar(100)notnull,principal_namevarchar(200)notnull,authorization_grant_typevarchar(100)notnull,attributesblobnull,statevarchar(500)null,authorization_code_valueblobnull,authorization_code_issued_attimestampnull,authorization_code_expires_attimestampnull,authorization_code_metadatablobnull,access_token_valueblobnull,access_token_issued_attimestampnull,access_token_expires_attimestampnull,access_token_metadatablobnull,access_token_typevarchar(100)null,access_token_scopesvarchar(1000)null,oidc_id_token_valueblobnull,oidc_id_token_issued_attimestampnull,oidc_id_token_expires_attimestampnull,oidc_id_token_metadatablobnull,refresh_token_valueblobnull,refresh_token_issued_attimestampnull,refresh_token_expires_attimestampnull,refresh_token_metadatablobnull);createtableoauth2_authorization_consent(registered_client_idvarchar(100)notnull,principal_namevarchar(200)notnull,authoritiesvarchar(1000)notnull,primarykey(registered_client_id,principal_name));createtableoauth2_registered_client(idvarchar(100)notnullprimarykey,client_idvarchar(100)notnull,client_id_issued_attimestampdefaultCURRENT_TIMESTAMPnotnull,client_secretvarchar(200)null,client_secret_expires_attimestampnull,client_namevarchar(200)notnull,client_authentication_methodsvarchar(1000)notnull,authorization_grant_typesvarchar(1000)notnull,redirect_urisvarchar(1000)null,scopesvarchar(1000)notnull,client_settingsvarchar(2000)notnull,token_settingsvarchar(2000)notnull);createtableusers(usernamevarchar(50)notnullprimarykey,passwordvarchar(500)notnull,enabledtinyint(1)notnull);createtableauthorities(usernamevarchar(50)notnull,authorityvarchar(50)notnull,constraintix_auth_usernameunique(username,authority),constraintfk_authorities_usersforeignkey(username)referencesusers(username));复制代码

初始化表,建表语句在哪里?

SpringSecurity的建表语句在

org/springframework/security/core/userdetails/jdbc/复制代码

SpringauthorizationServer的建表文件在:

org/springframework/security/oauth2/server/authorization//springframework/security/oauth2/server/authorization//springframework/security/oauth2/server/authorization/client/复制代码

都在jar包中,并且sql可能会有问题,请大家根据自己使用的数据库进行修改。

配置文件中配置数据库连接信息

server:port:8080spring:main:allow-bean-definition-overriding:truedatasource:url:jdbc:mysql://localhost:3306/spring-authorization-serverdriver-class-name::rootpassword:qwe!@#123复制代码

请根据自己的情况进行修改。

修改SpringSecurity和SpringauthorizationServer的配置。

修改SecurityConfig中的UserDetailsServicebean。

@AutowiredprivateDataSourcedataSource;@BeanpublicUserDetailsServiceuserDetailsService(){returnnewJdbcUserDetailsManager(dataSource);}复制代码

SpringAuthorizationServer有三张表,对应的bean也要修改三处

@AutowiredJdbcTemplatejdbcTemplate;@BeanpublicRegisteredClientRepositoryregisteredClientRepository(){returnnewJdbcRegisteredClientRepository(jdbcTemplate);}@BeanpublicOAuth2AuthorizationServiceauthorizationService(){returnnewJdbcOAuth2AuthorizationService(jdbcTemplate,registeredClientRepository());}@BeanpublicOAuth2AuthorizationConsentServiceauthorizationConsentService(){returnnewJdbcOAuth2AuthorizationConsentService(jdbcTemplate,registeredClientRepository());}复制代码

上述三个类对应SpringAuthorizationServer的三个表。

初始化表数据

需要初始化三张表数据,分别是users,authorities,oauth2_registered_client

users,authorities需要通过UserDetailsManager类来实现,我暂时使用junitTest来实现。

;;;;;;;;;;@SpringBootTestclassApplicationTests{/***初始化客户端信息*/@AutowiredprivateUserDetailsManageruserDetailsManager;/***创建用户信息*/@TestvoidtestSaveUser(){UserDetailsuserDetails=()..passwordEncoder(s-"{bcrypt}"+newBCryptPasswordEncoder().encode(s)).username("user").password("password").roles("ADMIN").build();(userDetails);}}复制代码

执行完毕后两个表的记录如下:

users:

username

password

enabled

user

2a2a2a10$

1

authories:

username

authority

user

ROLE_ADMIN

创建client信息

/***创建clientId信息*/@AutowiredprivateRegisteredClientRepositoryregisteredClientRepository;@Test@TestvoidtestSaveClient(){RegisteredClientregisteredClient=(().toString()).clientId("messaging-client").clientSecret("{bcrypt}"+newBCryptPasswordEncoder().encode("secret")).clientAuthenticationMethod(_SECRET_BASIC).authorizationGrantType(_CODE).authorizationGrantType(_TOKEN).authorizationGrantType(_CREDENTIALS).redirectUri("").redirectUri("").scope().scope("").scope("").clientSettings(().requireAuthorizationConsent(true).build()).build();(registeredClient);}复制代码

创建完成后,oauth2_registered_client表中的记录如下:

id

client_id

client_id_issued_at

client_secret

client_secret_expires_at

client_name

client_authentication_methods

authorization_grant_types

redirect_uris

scopes

client_settings

token_settings

f0ff36c2-1245-41a6-8c92-5ac5c049b268

messaging-client

2022-07-0220:35:26

{bcrypt}2a2a2a10$/O9UXXL721nH2s/2oOoH2UwOfc32.

NULL

f0ff36c2-1245-41a6-8c92-5ac5c049b268

client_secret_basic

refresh_token,client_credentials,authorization_code

openid,,

{"@class":"$UnmodifiableMap","":false,"":true}

{"@class":"$UnmodifiableMap","":true,"":["","RS256"],"":["",300.000000000],"":{"@class":"","value":"self-contained"},"":["",3600.000000000]}

测试服务

​授权码模式

访问:;client_id=messaging-clientscope=_uri=

输入用户名密码(user,password)后,勾选scope,确认后,通过地址栏能或得code。

获取到的code是

ZPO_JhUNM69j46JqZIGTTE_fvyzdZ30irinvQEW1DwFBQmWKhrwX-3GhR0a1l6uRoo4au9P1xl8Y6ig8SwDtXyTMLeSyHZC5PN8qwYwDkucQVqQLD7zNZLsdOIOwtLT5复制代码

获取token

结果是:

{"access_token":"eyJraWQiOiJmZGZkN21Njc2NTczNiwic2NvcGUiOlsibWVzc2FnZS5yZWFkIl0sImlzcyI6Imh0dHA6XC9cLzEyN_lzu4EypPPniy9_34ZquBgAMBGaRGZyLwuJZ7dWeKLv9WZLtgtZQiGM4Ru8Z3_Ub8JYAdW8Sik0ZigSHjMIV1HlI50RzEN1ZNQ2OrmRf-XPAhfAnvC2y4VLNIIgtG-hMq1v6xjr70AZMQanRseapv8sM72rNaD71OWP6FxJb5mN8ZVv3DbNjMRUJ4YF5OTINx6igUB0nONEE1KJTmEYIFz4de7O3RuNhtuyaKFq1BId5pqE17uwxIp7X0cX5MD680l2wsoILqW_WlULHBVc2SHaI--Ku65tePP-cPPw","refresh_token":"uWbL6c1QgwR-C5yORCY6qxR5-hN4qRZ91z6fsBtX0_6HkAeKaThattFt8tLwz91OsW7v5W2OwoDLnFwhjgfUCSKWxfyW2_OQMizlC0ytsgFRhYnwcy7j-2YB4EN0h9Es","scope":"","token_type":"Bearer","expires_in":299}复制代码

刷新token

结果是:

{"access_token":"eyJraWQiOiJmZGZkN21Njc2NTgwOSwic2NvcGUiOlsibWVzc2FnZS5yZWFkIl0sImlzcyI6Imh0dHA6XC9cLzEyN_AyF8ej843rhWGFh8ne2AoEAK98-kcsYh2B3JGzFnL5YBsDCSWhIDA6j-XLsF2bCcb7KDkREfeAL8tkkSE1wYm8nevcDufPMgyrZQEwHFWYoBAqCHUB2zPCx8PmInKa0aGkZIN6KJbdSWfp_-tFchi8sn6ZwPJkr5gU9NvoddbIAKm9A-6AT_EGXnlupo1ME26PptrLmrISOvDlbpOToCYMvSm9r22AzU2AITaM-9rujql_9H-Lj7ML8gMak2VJCPfSGpPczlvBG6fnP3xcwW6xXBd6wpe-tI7Cu6Bz36Hh2KIJlGs07_MvAxoCPixJIg","refresh_token":"uWbL6c1QgwR-C5yORCY6qxR5-hN4qRZ91z6fsBtX0_6HkAeKaThattFt8tLwz91OsW7v5W2OwoDLnFwhjgfUCSKWxfyW2_OQMizlC0ytsgFRhYnwcy7j-2YB4EN0h9Es","scope":"","token_type":"Bearer","expires_in":299}复制代码

客户端模式:

获取token

结果是:

{"access_token":"eyJraWQiOiJmZGZkN2udCIsIm5iZiI6MTY1Njc2NTg4Miwic2NvcGUiOlsib3BlbmlkIiwibWVzc2FnZS5yZWFkIiwibWVzc2FnZS53cml0ZSJdLCJpc3MiOiJodHRwOlwvXC8xMjc_IZM_4YbZL_1Rarpi5uBb6CbqUzqbUyAy-NXhFRqJfUkcVvXEQ8MWcvY6bPILg_Aqi4T5ZlFij0OACmqE3QmEenEkAJ8cxBA_fl9-k_Wcv8faepP5dlX8apPTX5i_6DW5p8IxtM1-tonhWNEEHjVVVpaktTd0yLYlhe_bbcVHpNAHpYXSO9sl18EamAJC5j9-rgN02w3XMPMd7oLxfR6IN74jOynSK4dZUmT6NnKqq9_V0DWGJWXHCjddiVN85VS5mojoz_74DaFT480fuy9XmhoYhv1xFqPxpqSUQrlCwKzAktbCvka8b9vPXQ","scope":"","token_type":"Bearer","expires_in":299}复制代码
自定义jwt字段

将上面的jwt解码后结果如下:

接下来我们增加一个自定义header和claim.

需要使用OAuth2TokenCustomizer来实现。

@BeanpublicJwtEncoderjwtEncoder(){returnnewNimbusJwtEncoder(jwkSource());}@BeanpublicOAuth2TokenGenerator?tokenGenerator(){JwtGeneratorjwtGenerator=newJwtGenerator(jwtEncoder());(jwtCustomizer());OAuth2AccessTokenGeneratoraccessTokenGenerator=newOAuth2AccessTokenGenerator();OAuth2RefreshTokenGeneratorrefreshTokenGenerator=newOAuth2RefreshTokenGenerator();returnnewDelegatingOAuth2TokenGenerator(jwtGenerator,accessTokenGenerator,refreshTokenGenerator);}@BeanpublicOAuth2TokenCustomizerJwtEncodingContextjwtCustomizer(){returncontext-{=();=();if(().equals(_TOKEN)){//Customizeheaders/claimsforaccess_("customerHeader","这是一个自定义header");("customerClaim","这是一个自定义Claim");}elseif(().getValue().equals(_TOKEN)){//Customizeheaders/claimsforid_token}};}复制代码

重启应用,我通过客户端模式获取token,并解码查看。

协议

SpringAuthorizationServer支持协议,同时也支持协议,该协议是OAuth2协议的上层协议,这里我就不解释了,可自行百度。

默认是不支持该协议的,需要我们进行配置。

用户端点

需要修改authorizationServerSecurityFilterChain为如下内容:

(oidc-{((oidcUserInfoAuthenticationContext-{OAuth2AccessTokenaccessToken=();MapString,Objectclaims=newHashMap();("url","");("accessToken",accessToken);("sub",().getPrincipalName());returnnewOidcUserInfo(claims);}));});(OAuth2ResourceServerConfigurer::jwt);@BeanpublicJwtDecoderjwtDecoder(JWKSourceSecurityContextjwkSource){(jwkSource);}复制代码

请注意:我的client(messaging-client)设置的时候scope设置了openid的支持。

测试:

授权码模式获取token:

;client_id=messaging-clientscope=openidredirect_uri=

请再次注意,这里的scope必须包含openid。

输入用户名密码确认后,获得的code如下:

nngt651MwKjuKPK0NJfxOU6KHE6okJ8RK3P7fdyJuc2o_GXdaDTrQGnBYjabcH9Bj9sZR6mxlZuojhldB349NZgKBfl8P67BWuX5jmCzXBc-a48pv-rPAyP7kBVvc031复制代码

获取token,得到的token是:

{"access_token":"eyJjdXN0b21lckhlYWRlciI6Iui_meaYr-S4gOS4quiHquWumuS5iWhlYWRlciIsImFsZyI6IlJTMjU2yQ2xhaW0iOiLov5nmmK_kuIDkuKroh6rlrprkuYlDbGFpbSIsIm5iZiI6MTY1Njc2OTMzNiwic2NvcGUiOlsib3BlbmlkIl0sImlzcyI6Imh0dHA6XC9cLzEyNFxd-1CIVE7hyojwxOT4d7QASUr33LdlWY8rlJ4vDm9VzQwQstB1K1bCgWg5ZcKpWdDXBrcA2ZL14tNvpDH9qsTfFpuIM1pGc-YWFL5k3CuPU0Us_U-P6gQqxpdJsBebctCXyPncmXA7zVp60kGPtenR0E9mjBx7DMZ30L00Hm9bZgHiy5G4QI87KRuJh9tR187ZK08IW3-0UEU-pzDhWE1YJaC0k4lQSC1ZplJq2q0Cmi2E_p2ZtxK4uduNol2-TZtiNs33O83XrAN1X5hke-ew","refresh_token":"RFxOTgEWcN__IbJC2D0I1qS0lq7rEDr7OTQApwZRq6edAQubjeGXTRn0_2VKnP2lYdSLiGKn4IzrrcPpJ7mFFEgppTQJpnGSX2kE_9tJ9D8ImFE8mOEc5HLkW0G6TXBR","scope":"openid","id_token":"eyJraWQiOiIwMzQ5Mlc3NhZ2luZy1jbGllbnQiLCJpc3MiOiJodHRwOlwvXC8xMjcSTwI47PFeKvUevmeeTCNRncQKWe_FBbgB8ZilI4Q944zLIUUUQmZHlANNfQ8EhBdbnJ2b3iblvhxSOGNCV_nSc2Rg0oikjpxbalWQjfuJHDsqKFny4ReU-ziZLc7Q5PVu3xuNfQN_iZOZq2c7pu6e5sP0p3YoD_YrjimAk0Ich0wrqiR_a9N5lT-EDh0iGWUc6US-FljEWxm-W1sUwS3E5xxSZxY2AJcmSXBIckwxVeWzG0VP9JoSEPrrs6tErzUwEJzkiw-zxYDPJvMb9sO8fw","token_type":"Bearer","expires_in":299}复制代码

通过token,获取OIDC的用户端点:

这里的sub就是用户的标志,当然也可以增加很多自定义信息。

修改如下:

@Bean@Order(_PRECEDENCE)publicSecurityFilterChainauthorizationServerSecurityFilterChain(HttpSecurityhttp)throwsException{OAuth2AuthorizationServerConfigurerHttpSecurityauthorizationServerConfigurer=newOAuth2AuthorizationServerConfigurer();RequestMatcherpointsMatcher=();(pointsMatcher).authorizeRequests(().authenticated()).csrf((pointsMatcher)).apply(authorizationServerConfigurer);http//Redirecttotheloginpagewhennotauthenticatedfromthe//((exceptions)-(newLoginUrlAuthenticationEntryPoint("/login")));//也可以使用如下代码,跳转到loginpage//(());(oidc-{((oidcUserInfoAuthenticationContext-{OAuth2AccessTokenaccessToken=();MapString,Objectclaims=newHashMap();("url","");("accessToken",accessToken);("sub",().getPrincipalName());returnnewOidcUserInfo(claims);}));});(OAuth2ResourceServerConfigurer::jwt);();}复制代码

重新获取用户信息,得到如下内容:

{"accessToken":{"tokenValue":"eyJjdXN0b21lckhlYWRlciI6Iui_meaYr-S4gOS4quiHquWumuS5iWhlYWRlciIsImFsZyI6IlJTMjU2yQ2xhaW0iOiLov5nmmK_kuIDkuKroh6rlrprkuYlDbGFpbSIsIm5iZiI6MTY1Njc3MDkxMSwic2NvcGUiOlsib3BlbmlkIl0sImlzcyI6Imh0dHA6XC9cLzEyNjpEakmd_byUlLkNC9sfGhae7t5U9fGgu6YzWhq3EKn-4g8TCJLMg6G8kmzCuqgLx6t_AaDDwhUQ7lsrVu99lahvE57mP80RmRGTBCnMbxfKbzvdj0nsMW0awYANd0R9m__gYL-O5WWAc7-qrcylPMzIKTOqT-cX2-pKzlAuhpcxsupQSNdnCEoH_VeoICMqcJnsz2l8mQjmHOnQ9YAddCvnLGeXcqyW24KhnUcJ0LwZLYrrvGdZ323lQKZSytTXfc4d9O1OzGkwR9OYmKif8Xbg","issuedAt":1656770912.000000000,"expiresAt":1656771212.000000000,"tokenType":{"value":"Bearer"},"scopes":["openid"]},"url":"""sub":"user"}复制代码

实际开发中,我们可以自定义,昵称、性别,头像等非敏感信息。

查看OpenID的配置

结果是:

{"issuer":"http://localhost:8080","authorization_point":"http://localhost:8080/oauth2/authorize","token_point":"http://localhost:8080/oauth2/token","token_point_auth_methods_supported":["client_secret_basic","client_secret_post","client_secret_jwt","private_key_jwt"],"jwks_uri":"http://localhost:8080/oauth2/jwks","userinfo_point":"http://localhost:8080/userinfo","response_types_supported":["code"],"grant_types_supported":["authorization_code","client_credentials","refresh_token"],"subject_types_supported":["public"],"id_token_signing_alg_values_supported":["RS256"],"scopes_supported":["openid"]}复制代码
客户端注册端点

客户端注册端点默认禁用,因为许多部署不需要动态客户端注册。

增加如下配置:

@Bean@Order(_PRECEDENCE)publicSecurityFilterChainauthorizationServerSecurityFilterChain(HttpSecurityhttp)throwsException{OAuth2AuthorizationServerConfigurerHttpSecurityauthorizationServerConfigurer=newOAuth2AuthorizationServerConfigurer();RequestMatcherpointsMatcher=();(pointsMatcher).authorizeRequests(().authenticated()).csrf((pointsMatcher)).apply(authorizationServerConfigurer);http//Redirecttotheloginpagewhennotauthenticatedfromthe//((exceptions)-(newLoginUrlAuthenticationEntryPoint("/login")));//也可以使用如下代码,跳转到loginpage//(());(oidc-{//用户信息((oidcUserInfoAuthenticationContext-{OAuth2AccessTokenaccessToken=();MapString,Objectclaims=newHashMap();("url","");("accessToken",accessToken);("sub",().getPrincipalName());returnnewOidcUserInfo(claims);}));//客户端注册(());});(OAuth2ResourceServerConfigurer::jwt);();}复制代码

请注意:

测试:

请求:;client_id=messaging-clientscope=_uri=

输入用户名密码后:

勾选scope,并提交,从地址栏中获取到code。

qdd5jgQxyfAlZELZr8kclamAaqkXlWxoEPa5h_7E0BbNLDkgfjDLnpo5SmPrFbZxZJVwO3KCMpmQD5D_y-2e_in8UD50ZpDPNs5GXjvOs_vU-tjhf0V-A7C9H1Phf9gw复制代码

获取accessToken

json结果是:

{"access_token":"eyJjdXN0b21lckhlYWRlciI6Iui_meaYr-S4gOS4quiHquWumuS5iWhlYWRlciIsImFsZyI6IlJTMjU2yQ2xhaW0iOiLov5nmmK_kuIDkuKroh6rlrprkuYlDbGFpbSIsIm5iZiI6MTY1Njg1NjAyMCwic2NvcGUiOlsiY2xpZW50LmNyZWF0ZSJdLCJpc3MiOiJodHRwOlwvXC8xMjc_udeDSZEdozy9iNCoEENcLWRsBh_RPRiQ6gx-IVXZouTnQkvl_nJChSDRv6a75HqDnxW3Q_iFQlxJx9wbXUIJ1k4mt2q0VqfPS5tTKoblhuEdAKyL90RLAEP1BSzxFFEYeSKIl-nEwsUWsZY9mqnzw33Z1dRVgZLrhIdhpwg41sSFKqw6B5yRzOHrc_0_nAW10TJK9ONbxrJvTc2ZHI8yLBjRoqEdFPgcOMkBHAH8baGsoHNLGEbVK4U8fb_hvZ1F9Ara3Aw3_yga4kJciGi_yt6y-A","refresh_token":"Hux9d04U-mi1GIFhy3t244xpS9wvrDaPSYXoR0gRP6vlQuKqAWlEER8RbdP7EAGOuFGoAyZ-nKAoxBL5JZxuwIyoGECrgHTEnof5eDaMVdrbNzwr8B8xxSZ0f-JicBys","scope":"","token_type":"Bearer","expires_in":299}复制代码

通过获取的accessToken,POST请求/connect/register接口

返回结果:

{"client_id":"Gw-kfSnh0R948WSJnAdIQCbXtcfifFhDygB7vPOWieI","client_id_issued_at":1656856140,"client_name":"MyExample","client_secret":"lmngmSlQNBJdCpBO4Ha2gubD0jtK_3Px2khf-u_tpyFZAT6imLV5F_bcsyZCZXPd","redirect_uris":["",""],"grant_types":["authorization_code"],"response_types":["code"],"token_point_auth_method":"client_secret_basic","id_token_signed_response_alg":"RS256","registration_client_uri":"","registration_access_token":"eyJjdXN0b21lckhlYWRlciI6Iui_meaYr-S4gOS4quiHquWumuS5iWhlYWRlciIsImFsZyI6IlJTMjU2XaWVJIiwiYXVkIjoiR3cta2ZTbmgwUjk0OFdTSm5BZElRQ2JYdGNmaWZGaER5Z0I3dlBPV2llSSIsImN1c3RvbWVyQ2xhaW0iOiLov5nmmK_kuIDkuKroh6rlrprkuYlDbGFpbSIsIm5iZiI6MTY1Njg1NjE0MCwic2NvcGUiOlsiY2xpZW50LnJlYWQiXSwiaXNzIjoiaHR0cDpcL1wvMTI3Ytv1rmrC8lbljycMXGcGRgBUSL1Zi5AFSoGCflYnVLvgHEQE70WLlcTFf4SW3JTQTBd2iTpTxAnNOQLG8UYgfDj4KQRAqkmdUUxNc-mPdpUNJQcDciNUgvuW5YhED3aPEVEp4tNfF47umyMUJ5kSGdFNOc3JDVI_nFE3TajxP1WYzvbF5SY8rq7TEtQPz1SB-YwSKZwusABjRQrmQAn0-oI-c-MvxjbyzMQPG6XXDArVv9rSfuouShU6VZYnPhL4t_D11RLPvL62AiLNya1VzIQ","client_secret_expires_at":0}复制代码

查看数据库表(oauth2_registered_client),可以看到多了一条记录

id

client_id

client_id_issued_at

client_secret

client_secret_expires_at

client_name

client_authentication_methods

authorization_grant_types

redirect_uris

scopes

client_settings

token_settings

f60a7102-08f6-4217-99c8-6d73a5dba9ef

Gw-kfSnh0R948WSJnAdIQCbXtcfifFhDygB7vPOWieI

2022-07-0321:49:01

lmngmSlQNBJdCpBO4Ha2gubD0jtK_3Px2khf-u_tpyFZAT6imLV5F_bcsyZCZXPd

NULL

MyExample

client_secret_basic

authorization_code

/callback,ht…

{"@class":"$UnmodifiableMap","":true,"":true}

{"@class":"$UnmodifiableMap","":true,"":["","RS256"],"":["",300.000000000],"":{"@class":"","value":"self-contained"},"":["",3600.000000000]}

说明客户端已经注册成功。

最新文章