Java重要面试名词整理(二十一):SpringSecurity

文章目录

  • SpringSecurity篇
    • 概念
      • 用户授权(访问控制)
      • JWT
      • JWT续期问题
      • Spring Authorization Server 是什么
      • OAuth2.0协议介绍
        • 角色
        • OAuth 2.0的运行流程
    • 授权模式详解
        • 客户端模式
        • 密码模式
        • 授权码模式
        • 简化模式
        • token刷新模式
    • OAuth 2.1 协议介绍
      • 授权码模式+PKCE扩展
      • 设备授权码模式
      • 拓展授权模式
    • OpenID Connect 1.0协议
    • Spring Authorization Server 实战
      • 认证(授权)服务器搭建
        • 授权码模式测试
    • SSO
    • OAuth2.1详细变化
      • 推荐使用 Authorization Code + PKCE
      • 隐式授权( Implicit Grant)已弃用
      • 密码授权 (Resource Owner Password Credentials Grant)已弃用
      • 使用 access_token 时, 不应该通过 URL 传递 token
      • 刷新令牌 (Refresh Token) 应该是一次性的
      • 回调地址(Redirect URI)应该精确匹配

SpringSecurity篇

概念

Spring Security是一个能够为基于Spring的企业应用系统提供声明式的安全访问控制解决方案的安全框架。Spring Security 主要实现了Authentication(认证,解决who are you? ) 和 AccessControl(访问控制,也就是what are you allowed to do?,也称为Authorization)。SpringSecurity在架构上将认证与授权分离,并提供了扩展点。

认证 :用户认证就是判断一个用户的身份是否合法的过程,用户去访问系统资源时系统要求验证用户的身份信息,身份合法方可继续访问,不合法则拒绝访问。常见的用户身份认证方式有:用户名密码登录,二维码登录,手机短信登录,指纹认证等方式。

授权: 授权是用户认证通过根据用户的权限来控制用户访问资源的过程,拥有资源的访问权限则正常访问,没有权限则拒绝访问。

在 Java 生态中,目前有 Spring Security 和 Apache Shiro 两个安全框架,可以完成认证和授权的功能。

  • Spring Security

  • Apache Shiro:一个功能强大且易于使用的Java安全框架,提供了认证,授权,加密,和会话管理。

用户授权(访问控制)

授权的方式包括 web授权和方法授权,web授权是通过url拦截进行授权,方法授权是通过方法拦截进行授权。

web授权: 基于url的访问控制

Spring Security可以通过 http.authorizeRequests() 对web请求进行授权保护 ,Spring Security使用标准Filter建立了对web请求的拦截,最终实现对资源的授权访问。配置顺序会影响之后授权的效果,越是具体的应该放在前面,越是笼统的应该放到后面。

JWT

什么是JWT

JSON Web Token(JWT)是一个开放的行业标准(RFC 7519),它定义了一种简介的、自包含的协议格式,用于在通信双方传递json对象,传递的信息经过数字签名可以被验证和信任。JWT可以使用HMAC算法或使用RSA的公钥/私钥对来签名,防止被篡改。 官网: https://jwt.io/ 标准: https://tools.ietf.org/html/rfc7519

使用 JWT 主要用来做下面两点:

  • 认证(Authorization):这是使用 JWT 最常见的一种情况,一旦用户登录,后面每个请求都会包含 JWT,从而允许用户访问该令牌所允许的路由、服务和资源。单点登录是当今广泛使用 JWT 的一项功能,因为它的开销很小。
  • 信息交换(Information Exchange):JWT 是能够安全传输信息的一种方式。通过使用公钥/私钥对 JWT 进行签名认证。此外,由于签名是使用 head 和 payload 计算的,因此你还可以验证内容是否遭到篡改。

JWT组成

一个JWT实际上就是一个字符串,它由三部分组成,头部(header)、载荷(payload)与签名(signature)。

头部(header)

头部用于描述关于该JWT的最基本的信息:类型(即JWT)以及签名所用的算法(如HMACSHA256或RSA)等

载荷(payload)

第二部分是载荷,就是存放有效信息的地方。这个名字像是特指飞机上承载的货品,这些有效信息包含三个部分:

  • 标准中注册的声明(建议但不强制使用)

iss: jwt签发者

sub: jwt所面向的用户

aud: 接收jwt的一方

exp: jwt的过期时间,这个过期时间必须要大于签发时间

nbf: 定义在什么时间之前,该jwt都是不可用的.

iat: jwt的签发时间

jti: jwt的唯一身份标识,主要用来作为一次性token,从而回避重放攻击。

  • 公共的声明 公共的声明可以添加任何的信息,一般添加用户的相关信息或其他业务需要的必要信息.但不建议添加敏感信息,因为该部分在客户端可解密.
  • 私有的声明 私有声明是提供者和消费者所共同定义的声明,一般不建议存放敏感信息,因为base64是对称解密的,意味着该部分信息可以归类为明文信息。

签名(signature)

jwt的第三部分是一个签证信息,这个签证信息由三部分组成:

  • header (base64后的)
  • payload (base64后的)
  • secret(盐,一定要保密)

这个部分需要base64加密后的header和base64加密后的payload使用.连接组成的字符串,然后通过header中声明的加密方式进行加盐secret组合加密,然后就构成了jwt的第三部分

JWT续期问题

JWT(JSON Web Token)通常是在用户登录后签发的,用于验证用户身份和授权。JWT 的有效期限(或称“过期时间”)通常是一段时间(例如1小时),过期后用户需要重新登录以获取新的JWT。然而,在某些情况下,用户可能会在JWT到期之前使用应用程序,这可能会导致应用程序不可用或需要用户重新登录。为了避免这种情况,通常有两种解决方案来处理JWT续期问题:

刷新令牌(Refresh Token)

刷新令牌是一种机制,它允许应用程序获取一个新的JWT,而无需用户进行身份验证。当JWT过期时,应用程序使用刷新令牌向身份验证服务器请求一个新的JWT,而无需提示用户输入其凭据。这样,用户可以继续使用应用程序,而不必重新登录。

自动延长JWT有效期

在某些情况下,JWT可以自动延长其有效期。例如,当用户在JWT过期前继续使用应用程序时,应用重新设置token过期时间。

Spring Authorization Server 是什么

Spring Authorization Server 是一个框架,它提供了 OAuth 2.1 和 OpenID Connect 1.0 规范以及其他相关规范的实现。它建立在 Spring Security 之上,为构建 OpenID Connect 1.0 身份提供者和 OAuth2 授权服务器产品提供了一个安全、轻量级和可定制的基础。说白了,Spring Authorization Server 就是一个认证(授权)服务器。

Springboot2.x Oauth2实现:

  • Spring Security Oauth2 支持搭建授权服务器和资源服务器

Springboot3.x Oauth2实现:

  • Spring Security6 自身提供资源和客户端类库支持
  • Spring Authorization Server支持授权服务器搭建

OAuth2.0协议介绍

OAuth 2.0 (Open Authorization)是一种开放标准的授权协议,允许用户授权第三方应用访问其在某个服务提供者上的受保护资源,而无需将其实际的凭证(如用户名和密码)分享给第三方应用。这种方式可以增加安全性,同时允许用户更好地控制其数据的访问权限。

OAuth2.0协议:https://datatracker.ietf.org/doc/html/rfc6749

角色
  • 客户端(client):使用授权服务器作为认证渠道的平台,一般指的是第三方应用。例如,微信提供 OAuth 2.0 认证平台,我们的 APP 支持微信登录,那么我们的 APP 对于微信服务来说就是客户端。又例如,我们是政府某一平台的服务,我们平台维护的数据代表着足够高的权威,那么其他政府部门或合作方,需要从我们的平台中查询数据,或者利用我们平台的认证进行登录,那么其他部门或合作方的应用就是客户端。
  • 资源服务器(resource server):简单的说,就是提供接口给客户端访问的服务器,访问资源服务器上受保护的接口,则需要带上令牌(token)。例如分布式微服务中的用户服务、订单服务等部署的服务器都属于资源服务器。
  • 资源所有者(resource owner):拥有该资源的主体对象,一般指用户。客户端向资源服务器请求获取用户数据时,资源所有者参与确认授权或拒绝操作。
  • 授权服务器(authorization server):对客户端和用户进行身份认证、授权的服务器,认证授权成功,则颁发令牌(token)。
OAuth 2.0的运行流程

(A)用户打开客户端以后,客户端要求用户给予授权。

(B)用户同意给予客户端授权。

(C)客户端使用上一步获得的授权,向授权服务器申请令牌。

(D)授权服务器对客户端进行认证以后,确认无误,同意发放令牌。

(E)客户端使用令牌,向资源服务器申请获取资源。

(F)资源服务器确认令牌无误,同意向客户端开放资源。

令牌(token)与密码(password)的作用是一样的,都可以进入系统,但是有三点差异。

(1)令牌是短期的,到期会自动失效,用户自己无法修改。密码一般长期有效,用户不修改,就不会发生变化。

(2)令牌可以被数据所有者撤销,会立即失效。密码一般不允许被他人撤销。

(3)令牌有权限范围(scope)。对于网络服务来说,只读令牌就比读写令牌更安全。密码一般是完整权限。

上面这些设计,保证了令牌既可以让第三方应用获得权限,同时又随时可控,不会危及系统安全。这就是 OAuth 2.0 的优点。

授权模式详解

授权码模式:应用最广泛,适合web应用/app/前端

资源所有者密码模式:官方应用

客户端凭证模式:适合无用户参与的应用

刷新令牌模式:适合令牌访问过期后刷新令牌

客户端模式

客户端模式(Client Credentials Grant)指客户端以自己的名义,而不是以用户的名义,向"服务提供商"进行授权。客户端模式是安全级别最低而且要求授权服务器对客户高度信任的模式,因为客户端向授权服务器请求认证授权的过程中,至始至终都没有用户的参与,未经过用户允许,客户端凭提供自己在授权服务器注册的信息即可在授权服务器完成认证授权,而客户端获得认证授权以后,则拥有从资源服务器操作用户数据的权限,这种模式一般应用于公司内部系统或者有着高度保密责任的合作伙伴之间的对接。

密码模式

如果你高度信任某个应用,RFC 6749 也允许用户把用户名和密码,直接告诉该应用。该应用就使用你的密码,申请令牌,这种方式称为"密码模式"(password)。

密码模式是一种安全级别较低而且要求资源拥有者(用户)完全信任客户端的模式,该模式可以理解为在客户端模式的基础上增加了对用户的账号、密码在认证服务器进行校验的操作,是客户端代理用户的操作。在 OAuth 2.1 中,密码模式已经被废除,在第三方平台上,使用密码模式,对于用户来说是一种非常不安全的行为,假设某平台客户端支持 QQ 登录,用户使用自己 QQ 的账号、密码在该平台上输入进行登录,则该平台将拥有用户 QQ 的账号、密码,对于用户来说,将自己 QQ 的账号、密码提供给第三方平台,这种行为是非常不安全的。

密码模式一般适合应用在自己公司内部使用的系统和自己公司的 app 产品

授权码模式

授权码(authorization code)方式,指的是第三方应用先申请一个授权码,然后再用该授权码获取令牌。

授权码模式是 OAuth 2.0 协议中安全级别最高的一种认证模式,他与密码模式一样,都需要使用到用户的账号信息在认证平台的登录操作,但有所不同的是,密码模式是要求用户直接将自己在认证平台的账号、密码提供给第三方应用(客户端),由第三方平台进行代理用户在认证平台的登录操作;而授权码模式则是用户在认证平台提供的界面进行登录,然后通过用户确认授权后才将一次性授权码提供给第三方应用,第三方应用拿到一次性授权码以后才去认证平台获取 token。

适用场景:目前市面上主流的第三方验证都是采用这种模式

简化模式

简化模式(也叫隐式模式)是相对于授权码模式而言的,对授权码模式的交互做了一下简化,省去了客户端使用授权码去认证服务器换取令牌(access_token)的操作,即用户在代理页面选择授权范围提交授权确认后,认证服务器通过客户端注册的回调地址直接就给客户端返回令牌(access_token)了。

这种方式把令牌直接传给前端,是很不安全的。因此,只能用于一些安全要求不高的场景,并且令牌的有效期必须非常短,通常就是会话期间(session)有效,浏览器关掉,令牌就失效了。

token刷新模式

令牌的有效期到了,如果让用户重新走一遍上面的流程,再申请一个新的令牌,很可能体验不好,而且也没有必要。OAuth 2.0 允许用户自动更新令牌。token刷新模式是对 access_token 过期的一种补办操作,这种补办操作,减少了用户重新操作登录的流程。OAuth 2.0 在给客户端颁发 access_token 的时候,同时也给客户端发放了 refresh_token,而 refresh_token 的有效期要远大于 access_token 的有效期。当客户端带着已过期的 access_token 去访问资源服务器中受保护的资源时,将会访问失败,此时就需要客户端使用 refresh_token 去获取新的 access_token。客户端获取到新的 access_token 后,就可以带上他去访问资源服务器中受保护的资源了。

OAuth 2.1 协议介绍

OAuth 2.1去掉了OAuth2.0中的密码模式、简化模式,增加了设备授权码模式,同时也对授权码模式增加了PKCE扩展。

OAuth2.1协议:https://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-1-07

授权码模式+PKCE扩展

授权码模式交互过程,见之前 OAuth2.0 授权码模式的讲解。这里要说的是授权码模式如何拓展 PKCE( Proof Key for Code Exchange 代码交换验证密钥)。

在授权码模式的交互工程中,有一个环节比较薄弱,这个环节就是用户在代理页面确认授权的时候,容易受到恶意程序的攻击,从而导致授权码被恶意程序窃取,进而通过授权码窃取令牌,当然这个前提也需要恶意程序已经植入到你的PC或手机当中

A. 客户端通过“/oauth2/authorize”地址向认证服务器发起获取授权码请求的时候增加两个参数,即 code_challenge 和 code_challenge_method,其中,code_challenge_method 是加密方法(例如:S256 或 plain),code_challenge 是使用 code_challenge_method 加密方法加密后的值。

B. 认证服务器给客户端返回授权码,同时记录下 code_challenge、code_challenge_method 的值。

C. 客户端使用 code 向认证服务器获取 Access Token 的时候,带上 code_verifier 参数,其值为步骤A加密前的初始值。

D. 认证服务器收到步骤 C 的请求时,将 code_verifier 的值使用 code_challenge_method 的方法进行加密,然后将加密后的值与步骤A中的 code_challenge 进行比较,看看是否一致。

上面交互过程中,恶意程序如果在B处截获授权码后,使用授权码向认证服务器换取 Access Token,但由于恶意程序没有 code_verifier 的值,因此在认证服务器无法校验通过,从而获取 Access Token 失败。

对于如何创建 code_challenge 的值,官网给出了下面两种对应的方法。

  • plain code_challenge = code_verifier 0.3.0被废弃了
  • S256 code_challenge = BASE64URL-ENCODE(SHA256(ASCII(code_verifier)))

设备授权码模式

设备授权码模式,是一种为解决不便在当前设备上进行文本输入而提供的一种认证授权模式,例如:智能电视、媒体控制台、数字相框、打印机等。大家也可以脑补一下一些扫码登录的情形。

拓展授权模式

OAuth2.1 也提供拓展授权模式的操作实现。虽然 OAuth2.1 移除了密码模式(password),但是通过拓展授权模式可以实现密码模式。在实际应用中,客户端、授权服务器、资源服务器往往都是同一家公司的产品,那么这个时候,使用账号、密码进行登录的情形也比较常见,此时就需要通过拓展授权模式来实现账号、密码登录了。

拓展授权模式官网文档: https://docs.spring.io/spring-authorization-server/docs/current/reference/html/guides/how-to-ext-grant-type.html

OpenID Connect 1.0协议

OpenID Connect 1.0:https://openid.net/specs/openid-connect-core-1_0.html

OpenID Connect 1.0 是 OAuth 2.0 协议之上的一个简单的身份层。其实就是客户端向认证服务器请求认证授权的时候,多返回一个 id_token,该 id_token 是一串使用 jwt 加密过的字符串

Spring Security OAuth2 Client组件介绍:

  • ClientRegistration:注册的客户端
  • ClientRegistrationRepository:ClientRegistration的存储仓库
  • OAuth2AuthorizedClient: 已授权过的客户端
  • OAuth2AuthorizedClientRepository :已授权过的客户端存储库持久化
  • OAuth2AuthorizationRequestRedirectFilter:该过滤器处理 /oauth2/authorization 路径,转发给 认证中心 对应的路径 /oauth2/authorize
  • OAuth2AuthorizationCodeGrantFilter:负责处理 认证中心 的授权码回调请求,如地址重定向
  • OAuth2LoginAuthenticationFilter:处理第三方认证的回调(该回调有授权码),拿着授权码到第三方认证服务器获取access_token和refresh_token

Spring Authorization Server 实战

版本要求:

  • Spring Authorization Server 版本:1.1.2
  • JDK 版本:17
  • Spring Boot 版本:3.1.4

认证(授权)服务器搭建

Spring Authorization Server重要组件:

  • SecurityFilterChain -> authorizationServerSecurityFilterChain: Spring Security的过滤器链,用于协议端点的。
  • SecurityFilterChain -> defaultSecurityFilterChain: Spring Security的过滤器链,用于Spring Security的身份认证
  • UserDetailsService :主要进行用户身份验证
  • RegisteredClientRepository:主要用于管理客户端
  • JWKSource:用于签名访问令牌
  • KeyPair: 启动时生成的带有密钥的KeyPair实例,用于创建上面的JWKSource
  • JwtDecoder:JwtDecoder的一个实例,用于解码已签名的访问令牌
  • AuthorizationServerSettings:用于配置Spring Authorization Server的AuthorizationServerSettings实例。

1)引入依赖

<!--Spring Authorization Server--> 
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-oauth2-authorization-server</artifactId> 
</dependency> 

2) 配置授权服务器

直接从官网https://docs.spring.io/spring-authorization-server/docs/current/reference/html/getting-started.html将 SecurityConfig 拷贝放到config下

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 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.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.oauth2.core.AuthorizationGrantType;
import org.springframework.security.oauth2.core.ClientAuthenticationMethod;
import org.springframework.security.oauth2.core.oidc.OidcScopes;
import org.springframework.security.oauth2.jwt.JwtDecoder;
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.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.MediaTypeRequestMatcher;import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.util.UUID;/*** https://docs.spring.io/spring-authorization-server/docs/current/reference/html/getting-started.html*/
@Configuration
@EnableWebSecurity
public class SecurityConfig {/***  Spring Authorization Server 相关配置*  主要配置OAuth 2.1和OpenID Connect 1.0* @param http* @return* @throws Exception*/@Bean @Order(1)public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http)throws Exception {OAuth2AuthorizationServerConfiguration.applyDefaultSecurity(http);http.getConfigurer(OAuth2AuthorizationServerConfigurer.class)//开启OpenID Connect 1.0(其中oidc为OpenID Connect的缩写).oidc(Customizer.withDefaults());  // Enable OpenID Connect 1.0http// Redirect to the login page when not authenticated from the// authorization endpoint//将需要认证的请求,重定向到login进行登录认证。.exceptionHandling((exceptions) -> exceptions.defaultAuthenticationEntryPointFor(new LoginUrlAuthenticationEntryPoint("/login"),new MediaTypeRequestMatcher(MediaType.TEXT_HTML)))// Accept access tokens for User Info and/or Client Registration// 使用jwt处理接收到的access token.oauth2ResourceServer((resourceServer) -> resourceServer.jwt(Customizer.withDefaults()));return http.build();}/***  Spring Security 过滤链配置(此处是纯Spring Security相关配置)*/@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.build();}/*** 设置用户信息,校验用户名、密码* @return*/@Bean public UserDetailsService userDetailsService() {UserDetails userDetails = User.withDefaultPasswordEncoder().username("fox").password("123456").roles("USER").build();//基于内存的用户数据校验return new InMemoryUserDetailsManager(userDetails);}/*** 注册客户端信息** 查询认证服务器信息* http://127.0.0.1:9000/.well-known/openid-configuration** 获取授权码* http://localhost:9000/oauth2/authorize?response_type=code&client_id=oidc-client&scope=profile&redirect_uri=http://www.baidu.com**/@Bean public RegisteredClientRepository registeredClientRepository() {RegisteredClient oidcClient = RegisteredClient.withId(UUID.randomUUID().toString()).clientId("oidc-client")//{noop}开头,表示“secret”以明文存储.clientSecret("{noop}secret").clientAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_BASIC).authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE).authorizationGrantType(AuthorizationGrantType.REFRESH_TOKEN).authorizationGrantType(AuthorizationGrantType.CLIENT_CREDENTIALS)//.redirectUri("http://spring-oauth-client:9001/login/oauth2/code/messaging-client-oidc")//我们暂时还没有客户端服务,以免重定向跳转错误导致接收不到授权码.redirectUri("http://www.baidu.com").postLogoutRedirectUri("http://127.0.0.1:8080/").scope(OidcScopes.OPENID).scope(OidcScopes.PROFILE).clientSettings(ClientSettings.builder().requireAuthorizationConsent(true).build()).build();//配置基于内存的客户端信息return new InMemoryRegisteredClientRepository(oidcClient);}/*** 配置 JWK,为JWT(id_token)提供加密密钥,用于加密/解密或签名/验签* JWK详细见:https://datatracker.ietf.org/doc/html/draft-ietf-jose-json-web-key-41*/@Bean public JWKSource<SecurityContext> 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);}/***  生成RSA密钥对,给上面jwkSource() 方法的提供密钥对*/private static KeyPair generateRsaKey() { KeyPair keyPair;try {KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");keyPairGenerator.initialize(2048);keyPair = keyPairGenerator.generateKeyPair();}catch (Exception ex) {throw new IllegalStateException(ex);}return keyPair;}/*** 配置jwt解析器*/@Bean public JwtDecoder jwtDecoder(JWKSource<SecurityContext> jwkSource) {return OAuth2AuthorizationServerConfiguration.jwtDecoder(jwkSource);}/*** 配置认证服务器请求地址*/@Bean public AuthorizationServerSettings authorizationServerSettings() {//什么都不配置,则使用默认地址return AuthorizationServerSettings.builder().build();}
}

在上面 SecurityConfig 代码中,我们已经开启了 OpenID Connect 1.0,于是我们就可以使用 http://127.0.0.1:9000/.well-known/openid-configuration 地址请求查看授权服务器信息了。

可以参考源码:OidcProviderConfigurationEndpointFilter,该类是 Spring Security 过滤链中的一个过滤器,当发起“/.well-known/openid-configuration”请求时,会被 OidcProviderConfigurationEndpointFilter 拦截

上面的配置信息中,其中 authorization_endpoint 为授权码的授权地址,device_authorization_endpoint 为设备授权码的授权地址,token_endpoint 为获取 token 的地址。

授权码模式测试

使用 http://localhost:9000/oauth2/authorize?response_type=code&client_id=oidc-client&scope=profile openid&redirect_uri=http://www.baidu.com 请求获取授权码

SSO

单点登录(Single Sign On),简称为 SSO,是比较流行的企业业务整合的解决方案之一。它的用途在于,不管多么复杂的应用群,只要在用户权限范围内,那么就可以做到,用户只需要登录一次就可以访问权限范围内的所有应用子系统。

OAuth2.1详细变化

OAuth 2.1 是 OAuth 2.0 的下一个版本, OAuth 2.1 根据最佳安全实践(BCP), 对 OAuth 2.0 协议进行整合和精简, 移除不安全的授权流程, 并发布了 OAuth 2.1 规范草案, 下面列出了和 OAuth 2.0 相比的主要区别。

https://fusionauth.io/articles/oauth/differences-between-oauth-2-oauth-2-1

推荐使用 Authorization Code + PKCE

根据 OAuth 2.0 安全最佳实践(Security Best Current Practices) 2.1.1 章节

隐式授权( Implicit Grant)已弃用

根据 OAuth 2.0 安全最佳实践(Security Best Current Practices) 2.1.2 章节

在 OAuth 2.1 规范草案中, 授权模式中已经找不到隐式授权(Implicit Grant), 我们知道, 隐式授权是 OAuth 2.0 中的授权模式, 是授权码模式的简化版本, 用户同意授权后, 直接就能返回访问令牌 access_token, 同时这种也是不安全的。

现在您可以考虑替换为 Authorization Code + PKCE 的授权模式。

密码授权 (Resource Owner Password Credentials Grant)已弃用

根据 OAuth 2.0 安全最佳实践(Security Best Current Practices) 2.4 章节

在 OAuth 2.1 规范草案中, 密码授权也被移除, 实际上这种授权模式在 OAuth 2.0中都是不推荐使用的, 密码授权的流程是, 用户把账号密码告诉客户端, 然后客户端再去申请访问令牌, 这种模式只在用户和客户端高度信任的情况下才使用。

使用 access_token 时, 不应该通过 URL 传递 token

根据 OAuth 2.0 安全最佳实践(Security Best Current Practices) 4.3.2 章节

刷新令牌 (Refresh Token) 应该是一次性的

根据 OAuth 2.0 安全最佳实践(Security Best Current Practices) 4.13.2 章节

回调地址(Redirect URI)应该精确匹配

[根据 OAuth 2.0 安全最佳实践(Security Best Current Practices) 4.1.3 章节](

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/502755.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

嵌入式linux中socket控制与实现

一、概述 1、首先网络,一看到这个词,我们就会想到IP地址和端口号,那IP地址和端口各有什么作用呢? (1)IP地址如身份证一样,是标识的电脑的,一台电脑只有一个IP地址。 (2)端口提供了一种访问通道,服务器一般都是通过知名端口号来识别某个服务。例如,对于每个TCP/IP实…

VScode SSH 错误:Got bad result from install script 解決

之前vscode好好的&#xff0c;某天突然连接报错如下 尝试1. 服务器没有断开,ssh可以正常连接 2. 用管理员权限运行vscode&#xff0c;无效 3. 删除服务器上的~/.vscode-server 文件夹&#xff0c;无效 试过很多后&#xff0c;原来很可能是前一天anaconda卸载导致注册表项 步…

GPT分区 使用parted标准分区划分,以及相邻分区扩容

parted 是一个功能强大的命令行工具&#xff0c;用于创建和管理磁盘分区表和分区。它支持多种分区表类型&#xff0c;如 MBR&#xff08;msdos&#xff09;、GPT&#xff08;GUID Partition Table&#xff09;等&#xff0c;并且可以处理大容量磁盘。parted 提供了一个交互式界…

关系分类(RC)模型和关系抽取(RE)模型的区别

目标不同 关系分类模型&#xff1a;对给定的实体对在给定句子中预测其关系类型。两阶段&#xff08;RC&#xff09; 关系抽取模型&#xff1a;从句子中识别出所有潜在实体对&#xff0c;并为其预测关系类型。一阶段&#xff08;NERRE&#xff09; 训练/预测阶段输入输出数据不…

VSCode编辑+GCC for ARM交叉编译工具链+CMake构建+OpenOCD调试(基于STM32的标准库/HAL库)

一、CMake安装 进入CMake官网的下载地址Get the Software&#xff0c;根据系统安装对应的Binary distributions。 或者在CMake——国内镜像获取二进制镜像安装包。 或者访问GitHub的xPack项目xPack CMake v3.28.6-1&#xff0c;下载即可。 记得添加用户/系统的环境变量&#…

【数据结构】链表(2):双向链表和双向循环链表

双向链表&#xff08;Doubly Linked List&#xff09; 定义&#xff1a; 每个节点包含三个部分&#xff1a; 数据域。前驱指针域&#xff08;指向前一个节点&#xff09;。后继指针域&#xff08;指向下一个节点&#xff09;。 支持从任意节点向前或向后遍历。 #define dat…

RK3588+麒麟国产系统+FPGA+AI在电力和轨道交通视觉与采集系统的应用

工业视觉识别系统厂家提供的功能主要包括&#xff1a; 这些厂家通过先进的视觉识别技术&#xff0c;实现图像的采集、处理与分析。系统能够自动化地完成质量检测、物料分拣、设备监控等任务&#xff0c;显著提升生产效率和产品质量。同时&#xff0c;系统具备高度的灵活性和可扩…

3 抢红包系统

我们还是按照我们分析问题的方法论开展 一 场景分析 我们分析的是集体活动的抢红包&#xff0c;比如春晚&#xff0c;大型活动红包&#xff0c;需要在网页操作的抢红包 抢红包的问题也是多个人抢资源的问题&#xff0c;可以和秒杀进行比对。但是也有很多不同的地方。 用户打…

数据库中的并发控制

并发操作带来的数据不一致性 1、并发控制:为了保证事务的隔离性和一致性&#xff0c;数据库管理系统需要对并发操作进行正确调度 并发控制的主要技术有:封锁、时间戳、乐观控制法、多版本并发控制等 并发操作带来的数据不一致性: ① 丟失修改:两个事务 T1 和 T2 读入同一数据…

ArcGIS Server 10.2授权文件过期处理

新的一年&#xff0c;arcgis server授权过期了&#xff0c;服务发不不了。查看ecp授权文件&#xff0c;原来的授权日期就到2024.12.31日。好吧&#xff0c;这里直接给出处理方法。 ArcGIS 10.2安装时&#xff0c;有的破解文件中会有含一个这样的注册程序&#xff0c;没有的话&…

学英语学压测:02jmeter组件-测试计划和线程组ramp-up参数的作用

&#x1f4e2;&#x1f4e2;&#x1f4e2;&#xff1a;先看关键单词&#xff0c;再看英文&#xff0c;最后看中文总结&#xff0c;再回头看一遍英文原文&#xff0c;效果更佳&#xff01;&#xff01; 关键词 Functional Testing功能测试[ˈfʌŋkʃənəl ˈtɛstɪŋ]Sample样…

MCGS学习记录

软件包 用户窗口 主窗口 元件&#xff1a;工具箱->输入框上面 数据对象 在工作台的实时数据库可以新增数据对象 理解为中间变量&#xff0c;控件改变其值&#xff0c;控件监测其值做出变化 基本属性 设定变量名和初始值 指针化&#xff1f; 变化时自动保存初始值&#x…

【网络协议】IPv4 地址分配 - 第一部分

文章目录 十进制与二进制网络如何被寻址地址类型网络地址广播地址主机地址 如何确定网络和主机部分的位数&#xff1f;网络中的主机数量与前缀号的关系计算每个前缀的主机数量公式 子网掩码二进制与操作&#xff08;Binary ANDing&#xff09;与操作&#xff08;AND Operation&…

数据挖掘——集成学习

数据挖掘——集成学习 集成学习Bagging&#xff1a;有放回采样随机森林 BoostingStacking 集成学习 集成学习&#xff08;Ensemble learning&#xff09;方法通过组合多种学习算法来获得比单独使用任何一种算法更好的预测性能。 动机是为了提高但分类器的性能 Bagging&…

ansible-性能优化

一. 简述&#xff1a; 搞过运维自动化工具的人&#xff0c;肯定会发现很多运维伙伴们经常用saltstack和ansible做比较&#xff0c;单从执行效率上来说&#xff0c;ansible确实比不上saltstack(ansible使用的是ssh,salt使用的是zeromq消息队列[暂没深入了解])&#xff0c;但其实…

NLP CH10 问答系统复习

1. 专家系统 特点 问题聚焦&#xff1a;限定在特定领域。数据结构化&#xff1a;使用结构化的领域知识。数据库支持&#xff1a;后台有一个数据库&#xff0c;保存系统可提供的各种数据。查询机制&#xff1a;用户提问时&#xff0c;系统将问题转换为 SQL 查询语句&#xff0…

vite6+vue3+ts+prettier+eslint9配置前端项目(后台管理系统、移动端H5项目通用配置)

很多小伙伴苦于无法搭建一个规范的前端项目&#xff0c;导致后续开发不规范&#xff0c;今天给大家带来一个基于Vite6TypeScriptVue3ESlint9Prettier的搭建教程。 目录 一、基础配置1、初始化项目2、代码质量风格的统一2.1、配置prettier2.2、配置eslint2.3、配置typescript 3、…

【2025年最新】OpenWrt 更换国内源的指南(图形界面版)

在上一篇文章中我们讲解了如何使用命令行更换国内源&#xff0c;如果你没有终端工具&#xff0c;或者不喜欢命令行&#xff0c;那么图形界面方式将会是更简单有效的方式。 命令行版本&#xff1a;【2025年最新】OpenWrt 更换国内源的指南(命令行)-CSDN博客 为什么选择通过图形…

uni-app:实现普通选择器,时间选择器,日期选择器,多列选择器

效果 选择前效果 1、时间选择器 2、日期选择器 3、普通选择器 4、多列选择器 选择后效果 代码 <template><!-- 时间选择器 --><view class"line"><view classitem1><view classleft>时间</view><view class"right&quo…

NVIDIA DLI课程《NVIDIA NIM入门》——学习笔记

先看老师给的资料&#xff1a; NVIDIA NIM是 NVIDIA AI Enterprise 的一部分&#xff0c;是一套易于使用的预构建容器工具&#xff0c;目的是帮助企业客户在云、数据中心和工作站上安全、可靠地部署高性能的 AI 模型推理。这些预构建的容器支持从开源社区模型到 NVIDIA AI 基础…