Spring Authorization Server (如何使用具有 PKCE 的单页应用程序进行身份验证-2)

使用 Spring Authorization Server 实现具有 PKCE 的单页应用程序进行身份验证

开启 CORS

SPA 由静态资源组成,可以通过多种方式进行部署。它可以与后端分开部署,例如使用 CDN 或单独的 Web 服务器,也可以使用 Spring Boot 与后端一起部署。

当 SPA 托管在不同的域下时,可以使用跨域资源共享 (CORS) 来允许应用程序与后端通信。

例如,如果你有一个在端口 4200 上本地运行的 Angular 开发服务器,你可以定义一个 CorsConfigurationSource @Bean并将 Spring Security 配置为允许使用 cors() DSL 的预检请求,如以下示例所示:

Enable CORS

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.http.MediaType;
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.oauth2.server.authorization.config.annotation.web.configuration.OAuth2AuthorizationServerConfiguration;
import org.springframework.security.oauth2.server.authorization.config.annotation.web.configurers.OAuth2AuthorizationServerConfigurer;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint;
import org.springframework.security.web.util.matcher.MediaTypeRequestMatcher;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;

@Configuration
@EnableWebSecurity
public class SecurityConfig {

	@Bean
	@Order(1)
	public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http)
			throws Exception {
		OAuth2AuthorizationServerConfiguration.applyDefaultSecurity(http);
		http.getConfigurer(OAuth2AuthorizationServerConfigurer.class)
			.oidc(Customizer.withDefaults());	// Enable OpenID Connect 1.0
		http
			// Redirect to the login page when not authenticated from the
			// authorization endpoint
			.exceptionHandling((exceptions) -> exceptions
				.defaultAuthenticationEntryPointFor(
					new LoginUrlAuthenticationEntryPoint("/login"),
					new MediaTypeRequestMatcher(MediaType.TEXT_HTML)
				)
			)
			// Accept access tokens for User Info and/or Client Registration
			.oauth2ResourceServer((oauth2) -> oauth2.jwt(Customizer.withDefaults()));

		return http.cors(Customizer.withDefaults()).build();
	}

	@Bean
	@Order(2)
	public SecurityFilterChain defaultSecurityFilterChain(HttpSecurity http)
			throws Exception {
		http
			.authorizeHttpRequests((authorize) -> authorize
				.anyRequest().authenticated()
			)
			// Form login handles the redirect to the login page from the
			// authorization server filter chain
			.formLogin(Customizer.withDefaults());

		return http.cors(Customizer.withDefaults()).build();
	}

	@Bean
	public CorsConfigurationSource corsConfigurationSource() {
		UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
		CorsConfiguration config = new CorsConfiguration();
		config.addAllowedHeader("*");
		config.addAllowedMethod("*");
		config.addAllowedOrigin("http://127.0.0.1:4200");
		config.setAllowCredentials(true);
		source.registerCorsConfiguration("/**", config);
		return source;
	}

}

配置一个公共客户端

SPA 无法安全地存储凭据,因此必须将其视为公共客户端。应要求公共客户端使用代码交换证明密钥 (PKCE)。

继续前面的示例,您可以将 Spring Authorization Server 配置为使用客户端身份验证方法 none 并需要 PKCE 来支持公共客户端,如以下示例所示:

spring:
  security:
    oauth2:
      authorizationserver:
        client:
          public-client:
            registration:
              client-id: "public-client"
              client-authentication-methods:
                - "none"
              authorization-grant-types:
                - "authorization_code"
              redirect-uris:
                - "http://127.0.0.1:4200"
              scopes:
                - "openid"
                - "profile"
            require-authorization-consent: true
            require-proof-key: true

注意:
requireProofKey 设置在忘记包含 code_challenge 和 code_challenge_method 查询参数的情况下非常有用,因为您将收到一个错误,指示在授权请求期间需要 PKCE,而不是在令牌请求期间出现常规客户端身份验证错误。

对客户端进行身份验证

将服务器配置为支持公共客户端后,一个常见问题是:如何对客户端进行身份验证并获取访问令牌?简短的回答是:与任何其他客户一样。

SPA 是基于浏览器的应用程序,因此使用与任何其他客户端相同的基于重定向的流程。此问题通常与可以通过 REST API 执行身份验证的期望有关,而 OAuth2 并非如此。
更详细的答案需要了解 OAuth2 和 OpenID Connect 中涉及的流程,在本例中为授权代码流程。授权代码流的步骤如下:

  • 客户端通过重定向到授权终结点来启动 OAuth2 请求。对于公共客户端,此步骤包括生成code_verifier和计算code_challenge,然后将其作为查询参数发送。

  • 如果用户未通过身份验证,授权服务器将重定向到登录页面。身份验证后,用户将再次重定向回授权终结点。

  • 如果用户尚未同意请求的范围,并且需要同意,则会显示同意页面。

  • 一旦用户同意,授权服务器就会生成一个authorization_code,并通过redirect_uri重定向回客户端。

  • 客户端通过查询参数获取authorization_code,并向令牌终结点执行请求。对于公共客户端,此步骤包括发送 code_verifier 参数而不是用于身份验证的凭据。

正如你所看到的,流程是相当复杂的,这只是一个概述。

  • 30
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
`spring-boot-starter-oauth2-authorization-server`是Spring Boot提供的OAuth2认证服务器的Starter,可以用于构建安全的OAuth2认证授权服务器。 以下是使用`spring-boot-starter-oauth2-authorization-server`构建OAuth2认证服务器的简单步骤: 1. 添加依赖 在`pom.xml`文件中添加以下依赖: ``` <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-oauth2-authorization-server</artifactId> </dependency> ``` 2. 配置认证服务器 在`application.yml`文件中添加以下配置: ``` spring: security: oauth2: authorization: server: jwt: signing-key: mySecretKey client: registration: my-client: client-id: my-client client-secret: mySecret scope: - read - write redirect-uri-template: http://localhost:8080/login/oauth2/code/my-client authorization-grant-type: authorization_code client-name: My Client provider: my-authorization-server: authorization-uri: http://localhost:8080/oauth2/authorize token-uri: http://localhost:8080/oauth2/token user-info-uri: http://localhost:8080/oauth2/userinfo user-name-attribute: name ``` 其中,`jwt.signing-key`是用于签名JWT的密钥,`client.registration`用于配置客户端信息,`client.provider`用于配置认证服务器信息。 3. 启动认证服务器 在Spring Boot应用程序中添加`@EnableAuthorizationServer`注解,启动OAuth2认证服务器: ```java @SpringBootApplication @EnableAuthorizationServer public class OAuth2AuthorizationServerApplication { public static void main(String[] args) { SpringApplication.run(OAuth2AuthorizationServerApplication.class, args); } } ``` 以上就是使用`spring-boot-starter-oauth2-authorization-server`构建OAuth2认证服务器的简单步骤。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

semicolon_helloword

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值