安全上

我刚刚宣布了新消息学习Spring Security课程,包括全部材料专注于春季安全的新OAuth2堆栈5:

>>看看这个课程

1.介绍

OAuth.是描述授权过程的开放标准。它可用于授权用户对API的访问。例如,REST API只能限制具有适当角色的注册用户的访问。

OAuth授权服务器负责验证用户并发出包含用户数据和正确访问策略的访问令牌。

在本教程中,我们将使用Spring Security OAuth授权服务器实验模块。

在此过程中,我们将创建一个客户机-服务器应用程序,该应用程序将从一个REST API获取Baeldung文章列表。金宝搏188体育客户端服务和服务器服务都需要OAuth身份验证。

2.授权服务器实现

让我们从查看OAuth授权服务器配置开始。它将作为文章资源和客户端服务器的身份验证源。

2.1。依赖性

首先,我们需要向我们的依赖添加一些依赖pom.xml文件:

<依赖项>  org.springframework.boot   Spring-Boot-Starter-Web   2.4.3   <依赖项>  org.springframework.boot spring-boot-starter-security 2.4.3   org.springframework.security.experimental spring-security-oauth2-authorization-server 0.1.0 

2.2。配置

现在,让我们配置auth服务器将运行的端口,方法是设置server.port物业在application.yml文件:

服务器:端口:9000

之后,我们可以转移到Spring bean配置。首先,我们需要@ configuration类并导入oauthauthorizationserverconfiguration..在配置类内部,我们将创建一些特定于oauth的bean。第一个将是客户机服务的存储库。在我们的示例中,我们将有一个单独的客户机,使用RegisteredClientBuilder类:

@configuration @import(oauth2authorizationsererverconfiguration.class)公共类授权者{@bean public haily computedclientrepository注册clientrepository(){nextendclient hexingclient = logegedclient.withid(uuid.randomuuuid()。toString()).clientid(“文章 - 客户端”).clientId(“文章 - 客户)”.clientic(“秘密”).clientauthenticationmethod(clientauthenticationmethod.basic).authorizationgranttype(authorizationgranttype.authorization_code).authorizationgranttype(authorizationgranttype.refresh_token).redirecturi(“http:// localhost:8080 / login / oauth2 / code / stricles-client-oidc”).redirecturi(“http:// localhost:8080 /授权”).cope(oidcopes.openid).cope(“articles.read”).build();返回新的InmemoryRegisteredClientRepository(注册值);} }

我们正在配置的属性是:

  • 客户端ID——Spring将使用它来识别哪个客户端正在尝试访问资源
  • 客户端密码 - 客户端和服务器已知的秘密,它在两者之间提供信任
  • 身份验证方法——在本例中,我们将使用基本身份验证,即用户名和密码
  • 授权授权类型——我们希望允许客户端同时生成授权代码和刷新令牌
  • 重定向URI——客户端将在基于重定向的流中使用它
  • 范围 - 此参数定义了客户端可能具有的授权。在我们的情况下,我们需要OidcScopes。OPENID和我们的定制一件物品。读

每个授权服务器都需要其签名键进行令牌以在安全域之间保留适当的边界。让我们生成一个2048字节的RSA密钥:

@Bean public JWKSource JWKSource () {RSAKey RSAKey = generateRsa();JWKSet JWKSet = new JWKSet(rsaKey);return (jwkSelector, securityContext) -> jwkSelector.select(jwkSet)} private static RSAKey generateRsa() {KeyPair KeyPair = generateRsaKey();RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();返回新的RSAKey.Builder(publicKey) .privateKey(privateKey) .keyID(UUID.randomUUID().toString()) .build();} private static KeyPair generateRsaKey() {KeyPairGenerator KeyPairGenerator = KeyPairGenerator. getinstance(“RSA”);keyPairGenerator.initialize (2048);返回keyPairGenerator.generateKeyPair (); }

除了签名密钥外,每个授权服务器还需要具有唯一的发行者URL。我们把它设为ahttp://127.0.0.1在端口9000.通过创建ProviderSettings豆角,扁豆:

@Bean公共ProviderSettings ProviderSettings(){返回新的ProviderSettings().issuer(“http://127.0.0.1:9000”);}

最后,我们将使用@EnableWebSecurity注释配置类:

@EnableWebSecurity公共类DefaultSecurityConfig {@Bean SecurityFilterchain defaultSecurityFilterchain(Httpsecurity HTTP)抛出异常{http.authorizeRequests(authorizeRequests  - > authorizeRequests.anyRequest()。Authendicated()).formlogin(withdefaults());返回http.build ();} // ...}

在这里,我们调用.authenticated authorizeRequests.anyRequest () ()要为所有请求要求身份验证,我们通过调用来提供基于表单的身份验证formLogin(违约())方法。

此外,我们将定义一组用于测试的示例用户。在这个例子中,让我们创建一个只有一个管理员用户的存储库:

@Bean UserDetailsService users() {UserDetails user = user . withdefaultpasswordencoder () .username("admin") .password("password") .build();返回新InMemoryUserDetailsManager(用户);}

3.资源服务器

现在,我们将创建一个资源服务器,该资源服务器将从Get端点返回一个文章列表。端点应仅允许对我们的OAuth服务器进行身份验证的请求。

3.1.依赖性

首先,让我们包含所需的依赖项:

<依赖项>  org.springframework.boot   Spring-Boot-Starter-Web   2.4.3   <依赖项>  org.springframework.boot spring-boot-starter-security 2.4.3   org.springframework.boot spring-boot-starter-oauth2-resource-server 2.4.3 

3.2.配置

在开始编写实现代码之前,应该配置application.yml文件。第一个是服务器端口:

服务器:端口:8090

接下来,是进行安全性配置的时候了。属性中配置的主机和端口需要为身份验证服务器设置正确的URLProviderSettings豆:早些时候

Spring: security: oauth2: resourceserver: jwt: issuer-uri: http://127.0.0.1:9000

现在,我们可以设置web安全配置。同样,我们要明确地指出,对文章资源的每个请求都应该得到授权并具有适当的文章权威:

@EnableWebSecurity public class ResourceServerConfig {@Bean SecurityFilterChain SecurityFilterChain (HttpSecurity http)抛出异常{http. mvcmatcher ("/articles/**") .authorizeRequests() .mvcMatchers("/articles/**").access("hasAuthority('SCOPE_articles.read')")和().oauth2ResourceServer() .jwt();返回http.build ();} }

如图所示,我们还调用oauth2ResourceServer ()方法配置OAuth服务器连接application.yml配置。

3.3.文章控制器

最后,我们将创建一个REST控制器,它将在GET /文章端点:

@RestController public class ArticlesController {@GetMapping("/articles") public String[] getArticles() {return new String[] {"Article 1", "Article 2", "Article 3"};} }

4.API客户端

在最后一部分中,我们将创建一个REST API客户机,它将从资源服务器获取文章列表。

4.1.依赖性

首先,让我们包含所需的依赖项:

<依赖项>  org.springframework.boot   Spring-Boot-Starter-Web   2.4.3   <依赖项>  org.springframework.boot spring-boot-starter-security 2.4.3   org.springframework.boot spring-boot-starter-oauth2-client 2.4.3   org.springframework spring-webflux 5.3.4   io.projectreactor.netty reactor-netty 1.0.4 

4.2。配置

正如我们前面所做的,我们将定义一些配置属性用于身份验证:

server: port: 8080 spring: security: oauth2: client: registration: articles-client-oidc: provider: spring client-id: articles-client client-secret: secret authorization-grant-type: authorization_code redirect-uri: "{baseUrl}/login/oauth2/code/{registrationId}"client-id: articles- client-secret: secret授权授权类型:authorization_code重定向uri:“{baseUrl}/authorized”读取client-name: articles-client-authorization-code provider: spring: issuer-uri: http://127.0.0.1:9000

现在,我们来创建WebClient实例执行到资源服务器的HTTP请求。我们将使用标准实现,只添加一个OAuth授权过滤器:

@Bean WebClient WebClient (OAuth2AuthorizedClientManager authorizedClientManager) {ServletOAuth2AuthorizedClientExchangeFilterFunction oauth2Client = new ServletOAuth2AuthorizedClientExchangeFilterFunction(authorizedClientManager);返回WebClient.builder() .apply(oauth2Client.oauth2Configuration()) .build();}

WebClient需要一个OAuth2authorizedClientManager.作为一个依赖。让我们创建一个默认实现:

@bean oauth2authorizedClientManager授权ClientManager(ClientRegistrationRepository ClientRegistrationRepository,OAuth2authorizedClientRepository授权ClientRepository){oauth2authorizedClientProvider授权克莱斯Provider= oauth2authorizedClientProviderBuilder.Builder().authorizationcode().build().build();defaultoauth2authorizedClientManager授权ClientManager = new defaultoauth2authorizedClientManager(ClientRegistrationRepository,授权ClientRepository);authorizedclientmanager.setauthorizedClientProvider(AuthorizedClientProvider);返回授权clientmanager;}

最后,我们将配置Web安全性:

@EnableWebSecurity公开课SecurityConfig {@ bean SecurityFilterChain SecurityFilterChain (HttpSecurity http)抛出异常{http .authorizeRequests(以- > authorizeRequests.anyRequest () .authenticated ()) .oauth2Login (oauth2Login - > oauth2Login.loginPage(“/ oauth2 /授权/ articles-client-oidc”)).oauth2Client (withDefaults ());返回http.build ();} }

在这里,以及其他服务器中,我们都需要对每个请求进行身份验证。此外,我们需要配置登录页面URL(定义在.ML.配置)和OAuth客户端。

4.3。文章端控制器

最后,我们可以创建数据访问控制器。我们将使用前面配置的WebClient发送HTTP请求到我们的资源服务器:

@RestController public class ArticlesController{私有WebClient WebClient;@GetMapping(value = "/articles") public String[] getArticles(@RegisteredOAuth2AuthorizedClient("articles-client-authorization-code") OAuth2AuthorizedClient authorizedClient) {return this。webClient .get() .uri(“http://localhost:8090/articles”).attributes(oauth2AuthorizedClient(authorizedClient)) .retrieve() .bodyToMono(String[].class) .block();} }

在上面的例子中,我们以一种形式从请求中获取OAuth授权令牌OAuth2AuthorizedClient类。属性自动地由Spring绑定@RegisterdOAuth2AuthorizedClient注释正确识别。在我们的情况下,它从中拉了article-client-authorizaiton-code我们之前在.ML.文件。

此授权令牌进一步传递给HTTP请求。

4.4。访问文章列表

现在,当我们进入浏览器并试图访问http:// localhost:8080 /文章页面下,我们将自动重定向到OAuth服务器登录页面下http://127.0.0.1:9000/loginURL:

在提供正确的用户名和密码后,授权服务器将把我们重定向回请求的URL—文章列表。

对文章端点的进一步请求不需要登录,因为访问令牌将存储在cookie中。

结论

在本文中,我们学习了如何设置、配置和使用Spring Security OAuth授权服务器。

一如既往,所有源代码都可用在github上

安全底

我刚刚宣布了新消息学习Spring Security课程,包括全部材料专注于春季安全的新OAuth2堆栈5:

>>看看这个课程
6评论
最老的
最新
内联反馈
查看所有评论
评论在本文上关闭!