Skip to content

一、基础版(不推荐)

授权服务器

授权服务器负责对用户进行身份验证,并颁发访问令(Access Token)。

1.添加依赖

xml
<!-- 授权服务器核心依赖 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>
<!-- springboot项目推荐-->
<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-oauth2-authorization-server</artifactId>
</dependency>

<!-- springboot不推荐-->
<!-- 
<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-oauth2-authorization-server</artifactId>
</dependency>
-->

2.核心安全配置

创建一个配置类,用于注册客户端信息、配置授权端点以及用户认证。

java
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
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.password.PasswordEncoder;
import org.springframework.security.oauth2.core.AuthorizationGrantType;
import org.springframework.security.oauth2.core.ClientAuthenticationMethod;
import org.springframework.security.oauth2.server.authorization.client.InMemoryRegisteredClientRepository;
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.settings.AuthorizationServerSettings;
import org.springframework.security.oauth2.server.authorization.settings.ClientSettings;
import org.springframework.security.oauth2.server.authorization.settings.TokenSettings;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
import org.springframework.security.web.SecurityFilterChain;
import java.time.Duration;
import java.util.UUID;

@Configuration
@EnableWebSecurity
public class AuthorizationServerConfig {

    // 配置HTTP安全过滤器链
    @Bean
    @Order(1)
    public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http) throws Exception {
        return http
                .securityMatcher("/oauth2/**") // 授权服务器端点
                .authorizeHttpRequests(authorize -> authorize.anyRequest().authenticated())
                .csrf(csrf -> csrf.ignoringRequestMatchers("/oauth2/**")) // 为授权端点禁用CSRF
                .formLogin(Customizer.withDefaults()) // 使用表单登录进行用户认证
                .build();
    }

    // 注册客户端信息(示例使用内存存储,生产环境应使用数据库)
    @Bean
    public RegisteredClientRepository registeredClientRepository() {
        RegisteredClient oidcClient = RegisteredClient.withId(UUID.randomUUID().toString())
                .clientId("test-client") // 客户端ID
                .clientSecret("{noop}test-secret") // 客户端密钥,{noop}表示明文,生产环境请加密
                .clientAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_BASIC)
                .authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE)
                .authorizationGrantType(AuthorizationGrantType.REFRESH_TOKEN)
                .redirectUri("http://127.0.0.1:8080/login/oauth2/code/test-client") // 回调地址
                .scope("read")
                .scope("write")
                .clientSettings(ClientSettings.builder().requireAuthorizationConsent(true).build())
                .tokenSettings(TokenSettings.builder()
                        .accessTokenTimeToLive(Duration.ofHours(1)) // 访问令牌有效期1小时
                        .refreshTokenTimeToLive(Duration.ofDays(1)) // 刷新令牌有效期1天
                        .build())
                .build();
        return new InMemoryRegisteredClientRepository(oidcClient);
    }

    // 配置授权服务器端点(如token uri, jwk set uri等)
    @Bean
    public AuthorizationServerSettings authorizationServerSettings() {
        return AuthorizationServerSettings.builder().build();
    }

    // 配置用户详情服务(示例使用内存用户,生产环境需对接数据库或LDAP)
    @Bean
    public UserDetailsService userDetailsService() {
        UserDetails userDetails = User.withUsername("user")
                .password("{noop}password") // 密码,{noop}表示明文
                .roles("USER")
                .build();
        return new InMemoryUserDetailsManager(userDetails);
    }
}

资源服务器

资源服务器负责验证访问令牌,并保护API资源。

1.添加依赖

xml
<!-- 资源服务器核心依赖 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-oauth2-resource-server</artifactId>
</dependency>

2.核心安全配置

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.oauth2.jwt.JwtDecoder;
import org.springframework.security.oauth2.jwt.NimbusJwtDecoder;
import org.springframework.security.web.SecurityFilterChain;

@Configuration
@EnableWebSecurity
public class ResourceServerConfig {

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        return http
                .authorizeHttpRequests(authorize -> authorize
                        .requestMatchers("/public/**").permitAll() // 公开接口
                        .anyRequest().authenticated() // 其他所有接口需要认证
                )
                // 配置为OAuth2资源服务器,并指定JWT解码方式
                .oauth2ResourceServer(oauth2 -> oauth2
                        .jwt(jwt -> jwt.decoder(jwtDecoder())) // 使用JWT令牌
                )
                .build();
    }

    // JWT解码器:配置如何验证令牌(此处假设授权服务器使用对称密钥加密)
    @Bean
    public JwtDecoder jwtDecoder() {
        // 重要:此处的密钥必须与授权服务器用于签发JWT的密钥一致
        String jwkSetUri = "http://localhost:9000/oauth2/jwks"; // 授权服务器的JWK Set端点
        return NimbusJwtDecoder.withJwkSetUri(jwkSetUri).build();
        // 如果是本地测试,也可以使用本地公钥:
        // return NimbusJwtDecoder.withPublicKey(publicKey).build();
    }
}

二、进阶版(推荐)

授权服务器

授权服务器负责对用户进行身份验证,并颁发访问令(Access Token)。

1.添加依赖

xml
<!-- 授权服务器核心依赖 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-oauth2-authorization-server</artifactId>
</dependency>

资源服务器

application.yml配置:

yml
  # 安全配置
  security:
    oauth2:
      resourceserver:
        jwt:
          issuer-uri: http://localhost:9000/auth
          jwk-set-uri: http://localhost:9000/auth/oauth2/jwks

Released under the MIT License.