springboot3 集成spring-authorization-server (一 基础篇)

springboot3 集成spring-authorization-server (一 基础篇)

码农世界 2024-06-16 后端 80 次浏览 0个评论

官方文档

Spring Authorization Server

环境介绍

java:17

SpringBoot:3.2.0

SpringCloud:2023.0.0

引入maven配置


    org.springframework.boot
    spring-boot-starter-security


    org.springframework.boot
    spring-boot-starter-oauth2-authorization-server


    org.springframework.boot
    spring-boot-starter-oauth2-client

AuthorizationServerConfig认证中心配置类

package com.auth.config;
import com.jilianyun.exception.ServiceException;
import com.nimbusds.jose.jwk.JWKSet;
import com.nimbusds.jose.jwk.RSAKey;
import com.nimbusds.jose.jwk.source.ImmutableJWKSet;
import com.nimbusds.jose.jwk.source.JWKSource;
import com.nimbusds.jose.proc.SecurityContext;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.MediaType;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.security.config.Customizer;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.oauth2.core.AuthorizationGrantType;
import org.springframework.security.oauth2.core.ClientAuthenticationMethod;
import org.springframework.security.oauth2.jwt.JwtDecoder;
import org.springframework.security.oauth2.server.authorization.client.JdbcRegisteredClientRepository;
import org.springframework.security.oauth2.server.authorization.client.RegisteredClient;
import org.springframework.security.oauth2.server.authorization.client.RegisteredClientRepository;
import org.springframework.security.oauth2.server.authorization.config.annotation.web.configuration.OAuth2AuthorizationServerConfiguration;
import org.springframework.security.oauth2.server.authorization.config.annotation.web.configurers.OAuth2AuthorizationServerConfigurer;
import org.springframework.security.oauth2.server.authorization.settings.AuthorizationServerSettings;
import org.springframework.security.oauth2.server.authorization.settings.ClientSettings;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.security.web.util.matcher.MediaTypeRequestMatcher;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.util.UUID;
/**
 * 

认证中心配置类

* * @author By: chengxuyuanshitang * Ceate Time 2024-05-07 11:42 */ @Slf4j @EnableWebSecurity @Configuration(proxyBeanMethods = false) public class AuthorizationServerConfig { /** * Security过滤器链,用于协议端点 * * @param http HttpSecurity * @return SecurityFilterChain */ @Bean public SecurityFilterChain authorizationServerSecurityFilterChain (HttpSecurity http) throws Exception { OAuth2AuthorizationServerConfiguration.applyDefaultSecurity (http); http.getConfigurer (OAuth2AuthorizationServerConfigurer.class) //启用OpenID Connect 1.0 .oidc (Customizer.withDefaults ()); http // 未从授权端点进行身份验证时重定向到登录页面 .exceptionHandling ((exceptions) -> exceptions .defaultAuthenticationEntryPointFor ( new LoginUrlAuthenticationEntryPoint ("/login"), new MediaTypeRequestMatcher (MediaType.TEXT_HTML) ) ) //接受用户信息和/或客户端注册的访问令牌 .oauth2ResourceServer ((resourceServer) -> resourceServer .jwt (Customizer.withDefaults ())); return http.build (); } /** * 用于认证的Spring Security过滤器链。 * * @param http HttpSecurity * @return SecurityFilterChain */ @Bean public SecurityFilterChain defaultSecurityFilterChain (HttpSecurity http) throws Exception { http.authorizeHttpRequests ((authorize) -> authorize .requestMatchers (new AntPathRequestMatcher ("/actuator/**"), new AntPathRequestMatcher ("/oauth2/**"), new AntPathRequestMatcher ("/**/*.json"), new AntPathRequestMatcher ("/**/*.css"), new AntPathRequestMatcher ("/**/*.html")).permitAll () .anyRequest ().authenticated () ) .formLogin (Customizer.withDefaults ()); return http.build (); } /** * 配置密码解析器,使用BCrypt的方式对密码进行加密和验证 * * @return BCryptPasswordEncoder */ @Bean public PasswordEncoder passwordEncoder () { return new BCryptPasswordEncoder (); } @Bean public UserDetailsService userDetailsService () { UserDetails userDetails = User.withUsername ("chengxuyuanshitang") .password (passwordEncoder ().encode ("chengxuyuanshitang")) .roles ("admin") .build (); return new InMemoryUserDetailsManager (userDetails); } /** * RegisteredClientRepository 的一个实例,用于管理客户端 * * @param jdbcTemplate jdbcTemplate * @param passwordEncoder passwordEncoder * @return RegisteredClientRepository */ @Bean public RegisteredClientRepository registeredClientRepository (JdbcTemplate jdbcTemplate, PasswordEncoder passwordEncoder) { RegisteredClient registeredClient = RegisteredClient.withId (UUID.randomUUID ().toString ()) .clientId ("oauth2-client") .clientSecret (passwordEncoder.encode ("123456")) // 客户端认证基于请求头 .clientAuthenticationMethod (ClientAuthenticationMethod.CLIENT_SECRET_BASIC) // 配置授权的支持方式 .authorizationGrantType (AuthorizationGrantType.AUTHORIZATION_CODE) .authorizationGrantType (AuthorizationGrantType.REFRESH_TOKEN) .authorizationGrantType (AuthorizationGrantType.CLIENT_CREDENTIALS) .redirectUri ("https://www.baidu.com") .scope ("user") .scope ("admin") // 客户端设置,设置用户需要确认授权 .clientSettings (ClientSettings.builder ().requireAuthorizationConsent (true).build ()) .build (); JdbcRegisteredClientRepository registeredClientRepository = new JdbcRegisteredClientRepository (jdbcTemplate); RegisteredClient repositoryByClientId = registeredClientRepository.findByClientId (registeredClient.getClientId ()); if (repositoryByClientId == null) { registeredClientRepository.save (registeredClient); } return registeredClientRepository; } /** * 用于签署访问令牌 * * @return JWKSource */ @Bean public JWKSource jwkSource () { KeyPair keyPair = generateRsaKey (); RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic (); RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate (); RSAKey rsaKey = new RSAKey.Builder (publicKey) .privateKey (privateKey) .keyID (UUID.randomUUID ().toString ()) .build (); JWKSet jwkSet = new JWKSet (rsaKey); return new ImmutableJWKSet<> (jwkSet); } /** * 创建RsaKey * * @return KeyPair */ private static KeyPair generateRsaKey () { KeyPair keyPair; try { KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance ("RSA"); keyPairGenerator.initialize (2048); keyPair = keyPairGenerator.generateKeyPair (); } catch (Exception e) { log.error ("generateRsaKey Exception", e); throw new ServiceException ("generateRsaKey Exception"); } return keyPair; } /** * 解码签名访问令牌 * * @param jwkSource jwkSource * @return JwtDecoder */ @Bean public JwtDecoder jwtDecoder (JWKSource jwkSource) { return OAuth2AuthorizationServerConfiguration.jwtDecoder (jwkSource); } @Bean public AuthorizationServerSettings authorizationServerSettings () { return AuthorizationServerSettings.builder ().build (); } }

详细介绍

SecurityFilterChain authorizationServerSecurityFilterChain (HttpSecurity http) 

Spring Security的过滤器链,用于协议端点

springboot3 集成spring-authorization-server (一 基础篇)

SecurityFilterChain defaultSecurityFilterChain (HttpSecurity http)
 Security的过滤器链,用于Security的身份认证

springboot3 集成spring-authorization-server (一 基础篇)

PasswordEncoder passwordEncoder ()
 配置密码解析器,使用BCrypt的方式对密码进行加密和验证

springboot3 集成spring-authorization-server (一 基础篇)

UserDetailsService userDetailsService ()

用于进行用户身份验证

springboot3 集成spring-authorization-server (一 基础篇)

RegisteredClientRepository registeredClientRepository (JdbcTemplate jdbcTemplate, PasswordEncoder passwordEncoder)
用于管理客户端

springboot3 集成spring-authorization-server (一 基础篇)

JWKSource jwkSource () 
用于签署访问令牌

springboot3 集成spring-authorization-server (一 基础篇)

 KeyPair generateRsaKey ()
创建RsaKey

springboot3 集成spring-authorization-server (一 基础篇)

 JwtDecoder jwtDecoder (JWKSource jwkSource)
解码签名访问令牌

springboot3 集成spring-authorization-server (一 基础篇)

 AuthorizationServerSettings authorizationServerSettings () 

配置Spring Authorization Server的AuthorizationServerSettings实例

springboot3 集成spring-authorization-server (一 基础篇)

初始化自带的数据表

自带的表在spring-security-oauth2-authorization-server-1.2.0.jar 中 下面是对应的截图

springboot3 集成spring-authorization-server (一 基础篇)

springboot3 集成spring-authorization-server (一 基础篇)

对应的SQL
-- 已注册的客户端信息表
CREATE TABLE oauth2_registered_client
(
    id                            varchar(100)                            NOT NULL,
    client_id                     varchar(100)                            NOT NULL,
    client_id_issued_at           timestamp     DEFAULT CURRENT_TIMESTAMP NOT NULL,
    client_secret                 varchar(200)  DEFAULT NULL,
    client_secret_expires_at      timestamp     DEFAULT NULL,
    client_name                   varchar(200)                            NOT NULL,
    client_authentication_methods varchar(1000)                           NOT NULL,
    authorization_grant_types     varchar(1000)                           NOT NULL,
    redirect_uris                 varchar(1000) DEFAULT NULL,
    post_logout_redirect_uris     varchar(1000) DEFAULT NULL,
    scopes                        varchar(1000)                           NOT NULL,
    client_settings               varchar(2000)                           NOT NULL,
    token_settings                varchar(2000)                           NOT NULL,
    PRIMARY KEY (id)
);
-- 认证授权表
CREATE TABLE oauth2_authorization_consent
(
    registered_client_id varchar(100)  NOT NULL,
    principal_name       varchar(200)  NOT NULL,
    authorities          varchar(1000) NOT NULL,
    PRIMARY KEY (registered_client_id, principal_name)
);
/*
IMPORTANT:
    If using PostgreSQL, update ALL columns defined with 'blob' to 'text',
    as PostgreSQL does not support the 'blob' data type.
*/
-- 认证信息表
CREATE TABLE oauth2_authorization
(
    id                            varchar(100) NOT NULL,
    registered_client_id          varchar(100) NOT NULL,
    principal_name                varchar(200) NOT NULL,
    authorization_grant_type      varchar(100) NOT NULL,
    authorized_scopes             varchar(1000) DEFAULT NULL,
    attributes                    blob          DEFAULT NULL,
    state                         varchar(500)  DEFAULT NULL,
    authorization_code_value      blob          DEFAULT NULL,
    authorization_code_issued_at  timestamp     DEFAULT NULL,
    authorization_code_expires_at timestamp     DEFAULT NULL,
    authorization_code_metadata   blob          DEFAULT NULL,
    access_token_value            blob          DEFAULT NULL,
    access_token_issued_at        timestamp     DEFAULT NULL,
    access_token_expires_at       timestamp     DEFAULT NULL,
    access_token_metadata         blob          DEFAULT NULL,
    access_token_type             varchar(100)  DEFAULT NULL,
    access_token_scopes           varchar(1000) DEFAULT NULL,
    oidc_id_token_value           blob          DEFAULT NULL,
    oidc_id_token_issued_at       timestamp     DEFAULT NULL,
    oidc_id_token_expires_at      timestamp     DEFAULT NULL,
    oidc_id_token_metadata        blob          DEFAULT NULL,
    refresh_token_value           blob          DEFAULT NULL,
    refresh_token_issued_at       timestamp     DEFAULT NULL,
    refresh_token_expires_at      timestamp     DEFAULT NULL,
    refresh_token_metadata        blob          DEFAULT NULL,
    user_code_value               blob          DEFAULT NULL,
    user_code_issued_at           timestamp     DEFAULT NULL,
    user_code_expires_at          timestamp     DEFAULT NULL,
    user_code_metadata            blob          DEFAULT NULL,
    device_code_value             blob          DEFAULT NULL,
    device_code_issued_at         timestamp     DEFAULT NULL,
    device_code_expires_at        timestamp     DEFAULT NULL,
    device_code_metadata          blob          DEFAULT NULL,
    PRIMARY KEY (id)
);

application.yml中数据库配置

spring:
  profiles:
    active: dev
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://192.168.0.1:3306/auth?characterEncoding=utf8&useSSL=false&serverTimezone=GMT%2B8&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true
    username: auth
    password: 12345

springboot3 集成spring-authorization-server (一 基础篇)

启动AuthServerApplication

启动完成后查看数据库的oauth2_registered_client表中有一条数据;

springboot3 集成spring-authorization-server (一 基础篇)

查看授权服务配置

地址:http://127.0.0.1:8801/.well-known/openid-configuration

springboot3 集成spring-authorization-server (一 基础篇)

访问/oauth2/authorize前往登录页面

地址:ip/端口/oauth2/authorize?client_id=app-client&response_type=code&scope=user&redirect_uri=https://www.baidu.com

实例:

http://127.0.0.1:8801/oauth2/authorize?client_id=app-client&response_type=code&scope=user&redirect_uri=https://www.baidu.com

浏览器跳转到:http://127.0.0.1:8801/login

springboot3 集成spring-authorization-server (一 基础篇)

输入上面配置的密码和账号。我这里都是:chengxuyuanshitang 点击提交。跳转

springboot3 集成spring-authorization-server (一 基础篇)

跳转到

springboot3 集成spring-authorization-server (一 基础篇)

网址栏的地址:https://www.baidu.com/?code=S73PUvl26OSxBc-yBbRRPJMTzcvE2x-VFZGXFPjpvOXHrecbY3Thsj6aOxPdN31H4a6GUgujSc1D4lj9D1ApIUAfZi55YJLqiRLpCivb-Is_4h3grILgR8H8M9UWyhJt

code的值就是=后面的

code=S73PUvl26OSxBc-yBbRRPJMTzcvE2x-VFZGXFPjpvOXHrecbY3Thsj6aOxPdN31H4a6GUgujSc1D4lj9D1ApIUAfZi55YJLqiRLpCivb-Is_4h3grILgR8H8M9UWyhJt

获取token

请求地址:http://127.0.0.1:8801/oauth2/token?grant_type=authorization_code&redirect_uri=https://www.baidu.com&code=S73PUvl26OSxBc-yBbRRPJMTzcvE2x-VFZGXFPjpvOXHrecbY3Thsj6aOxPdN31H4a6GUgujSc1D4lj9D1ApIUAfZi55YJLqiRLpCivb-Is_4h3grILgR8H8M9UWyhJt

用postman请求

springboot3 集成spring-authorization-server (一 基础篇)

添加header参数

header中的 Authorization参数:因为我们用的客户端认证方式 为  client_secret_basic ,这个需要传参,还有一些其他的认证方式,

client_secret_basic: 将 clientId 和 clientSecret 通过 : 号拼接,并使用 Base64 进行编码得到一串字符,再在前面加个 注意有个 Basic   前缀(Basic后有一个空格), 即得到上面参数中的 Basic 。

我的是:app-client:123456

Base64 进行编码:YXBwLWNsaWVudDoxMjM0NTY=

springboot3 集成spring-authorization-server (一 基础篇)

返回:

{
    "access_token": "eyJraWQiOiI2ZTJmYTA5ZS0zMmYzLTQ0MmQtOTM4Zi0yMzJjNDViYTM1YmMiLCJhbGciOiJSUzI1NiJ9.eyJzdWIiOiJjaGVuZ3h1eXVhbnNoaXRhbmciLCJhdWQiOiJhcHAtY2xpZW50IiwibmJmIjoxNzE1MDcxOTczLCJzY29wZSI6WyJ1c2VyIl0sImlzcyI6Imh0dHA6Ly8xMjcuMC4wLjE6ODgwMSIsImV4cCI6MTcxNTA3MjI3MywiaWF0IjoxNzE1MDcxOTczLCJqdGkiOiI0MWI4ZGZmZS03MTI2LTQ4NWYtODRmYy00Yjk4OGE0N2ZlMzUifQ.VxP2mLHt-eyXHZOI36yhVlwC2UQEdAtaRBKTWwJn1bFup0ZjGbZfgxENUb1c03yjcki2H-gCW4Jgef11BMNtjyWSnwMHVWLB9fcT3rRKDQWwoWqBYAcULS8oC5n8qTZwffDSrnjepMEbw4CblL3oH7T9nLProTXQP326RIE1RczsUYkteUCkyIvKTSs3ezOjIVR1GyCs_Cl1A_3OllmkGnSO2q-NKkwasrQjMuuPTY3nhDyDGiefYlfDEcmzz1Yk_FE42P7PEeyqmZwAj7vUnE4brQuNqipaMsS7INe_wTE1kJv-arfbnUo_zQdipHxIhsDgoLaPlSSecQ31QgwEHA",
    "refresh_token": "TqJyWbLWe5Yww6dOV89zDbO0C3YEBA__0TJU_GclmQTAH92SSQ2OvdMChIdln97u1WsA7G7n3BqzNZBjPRU7xmkRooa5ifsMBJ-d3C4kPmuPQI-Bmbq20pck-QEk0Dqt",
    "scope": "user",
    "token_type": "Bearer",
    "expires_in": 300
}

springboot3 集成spring-authorization-server (一 基础篇)

访问接口/userinfo

请求地址:http://127.0.0.1:8801/userinfo

添加header参数:Authorization: Bearer +空格+ ${access_token}

springboot3 集成spring-authorization-server (一 基础篇)




springboot3 集成spring-authorization-server (一 基础篇)

转载请注明来自码农世界,本文标题:《springboot3 集成spring-authorization-server (一 基础篇)》

百度分享代码,如果开启HTTPS请参考李洋个人博客
每一天,每一秒,你所做的决定都会改变你的人生!

发表评论

快捷回复:

评论列表 (暂无评论,80人围观)参与讨论

还没有评论,来说两句吧...

Top