行业资讯
Spring Security OAuth2资源服务器实战:构建受保护的RESTful API
1. 项目概述与核心思路在完成了OAuth2授权服务器的基础搭建和核心配置之后我们终于来到了实战环节的第三部分。这一部分我们将聚焦于如何让这个认证服务真正“活”起来也就是实现资源服务器的保护并完成一个从授权到访问受保护资源的完整闭环。很多朋友在搭建OAuth2时常常卡在授权服务器能发令牌但客户端拿着令牌却访问不了资源这一步感觉前后脱节。今天我们就来彻底打通这“最后一公里”。简单来说一个完整的OAuth2流程包含四个角色资源拥有者用户、客户端我们的前端应用或第三方应用、授权服务器我们正在搭建的和资源服务器存放用户数据、API接口的服务。前两篇我们重点打造了授权服务器这个“发证机关”现在我们需要建立一个“检查站”——资源服务器它负责验证客户端带来的“令牌”Token是否合法、有效并据此决定是否放行允许访问背后的资源。本部分的核心目标非常明确基于Spring Security OAuth2 Resource Server组件快速构建一个受保护的RESTful API然后我们会创建一个简单的测试客户端模拟完整的授权码模式流程从跳转到登录、授权、回调、获取令牌再到使用令牌访问受保护的API并观察整个过程。我会把其中容易混淆的配置项、依赖冲突的坑、以及调试技巧毫无保留地分享出来。无论你是想为微服务架构提供统一的认证入口还是为移动端、前后端分离应用提供安全的API访问方案这篇实战指南都能给你一套可直接复用的代码和清晰的思路。2. 核心依赖引入与版本锁定开始编码前依赖管理是重中之重Spring Security OAuth2的依赖关系在Spring Boot 2.x之后有较大变化处理不当极易出现ClassNotFoundException或配置不生效的问题。这里我们基于Spring Boot 2.7.x一个长期支持且稳定的版本进行构建。在你的pom.xml中确保有以下核心依赖。请注意我们不再使用古老的spring-security-oauth2-autoconfigure而是采用Spring官方在Spring Boot 2.x推荐的OAuth2资源服务器支持方式。dependencies !-- Spring Boot Web Starter -- dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-web/artifactId /dependency !-- Spring Security Starter - 核心安全框架 -- dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-security/artifactId /dependency !-- OAuth2 资源服务器支持 - 这是保护API的关键 -- dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-oauth2-resource-server/artifactId /dependency !-- JWT支持用于解析和验证JWT令牌 -- dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-oauth2-client/artifactId /dependency !-- 使用JWT令牌需要这个库来解析 -- dependency groupIdcom.nimbusds/groupId artifactIdnimbus-jose-jwt/artifactId version9.31/version /dependency !-- 数据库相关沿用之前的用户存储 -- dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-data-jpa/artifactId /dependency dependency groupIdmysql/groupId artifactIdmysql-connector-java/artifactId scoperuntime/scope /dependency !-- 工具类如 Lombok -- dependency groupIdorg.projectlombok/groupId artifactIdlombok/artifactId optionaltrue/optional /dependency /dependencies注意版本一致性spring-boot-starter-oauth2-resource-server会自动引入一系列相关的Spring Security OAuth2依赖版本由Spring Boot父POM统一管理这是最省心且避免冲突的方式。手动指定某些OAuth2依赖的版本是常见错误来源。关键依赖解析spring-boot-starter-oauth2-resource-server这是本篇的主角。它提供了将你的Spring Boot应用转变为OAuth2资源服务器所需的一切包括自动配置JwtDecoder、OpaqueTokenIntrospector以及相关的安全过滤器链。nimbus-jose-jwtSpring Security默认使用Nimbus库来处理JWTJSON Web Token的编码和解码。虽然资源服务器starter可能传递依赖它但显式声明一个稳定版本可以避免潜在的依赖冲突。spring-boot-starter-oauth2-client这个依赖在本篇主要用于我们的测试客户端应用使其能够发起OAuth2登录流程。如果你的资源服务器纯粹只提供API不包含前端页面这个依赖可以不加。3. 资源服务器配置详解资源服务器的配置核心是告诉Spring Security如何验证访问令牌Token。我们使用的是JWT令牌因此需要配置一个JwtDecoder来解析和验证JWT签名。配置集中在application.yml和一个配置类中。3.1 应用配置文件首先在application.yml中我们需要指定授权服务器的地址颁发令牌的地方和资源服务器自身的配置。server: port: 8081 # 资源服务器运行在8081端口与授权服务器(8080)区分 spring: application: name: resource-server # 资源服务器安全配置 security: oauth2: resourceserver: jwt: # 这是最关键的一步指定JWT令牌的验签地址。 # 资源服务器会向这个端点发起请求获取用于验证JWT签名的公钥JWK Set。 issuer-uri: http://localhost:8080 # 如果你的授权服务器端点有上下文路径例如 http://localhost:8080/auth 则这里应为 http://localhost:8080/authissuer-uri配置是Spring Security OAuth2 Resource Server的“魔法”所在。配置后应用启动时会自动向{issuer-uri}/.well-known/openid-configurationOIDC发现端点或{issuer-uri}/oauth/token_keyOAuth2令牌密钥端点发起请求获取JWK SetJSON Web Key Set从而自动构建JwtDecoder。这要求你的授权服务器上篇搭建的必须暴露这些标准端点。3.2 资源服务器安全配置类接下来我们需要通过一个Java配置类来定义资源服务器的安全规则哪些路径需要保护哪些可以公开访问以及使用什么样的认证方式。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.http.SessionCreationPolicy; import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationConverter; import org.springframework.security.oauth2.server.resource.authentication.JwtGrantedAuthoritiesConverter; import org.springframework.security.web.SecurityFilterChain; Configuration public class ResourceServerConfig { Bean public SecurityFilterChain resourceServerFilterChain(HttpSecurity http) throws Exception { http // 指定这是一个资源服务器配置OAuth2资源服务器相关功能 .oauth2ResourceServer(oauth2 - oauth2 .jwt(jwt - jwt // 可以在此处自定义JWT认证转换器将JWT中的声明claims转换为Spring Security的权限 .jwtAuthenticationConverter(jwtAuthenticationConverter()) ) ) // 授权配置定义URL的访问规则 .authorizeHttpRequests(authorize - authorize // 公开端点无需认证即可访问 .requestMatchers(/api/public/**).permitAll() // 受保护端点需要有效的JWT令牌并且要求拥有SCOPE_read权限对应JWT中的scope .requestMatchers(/api/protected/**).hasAuthority(SCOPE_read) // 更细粒度的控制需要SCOPE_write权限 .requestMatchers(/api/admin/**).hasAuthority(SCOPE_write) // 其他所有请求都需要认证即有效的JWT令牌 .anyRequest().authenticated() ) // 由于是API服务我们通常使用无状态会话即不创建HttpSession .sessionManagement(session - session .sessionCreationPolicy(SessionCreationPolicy.STATELESS) ) // 禁用CSRF保护因为API通常使用令牌而非Cookie进行认证CSRF不适用 .csrf(csrf - csrf.disable()); return http.build(); } /** * 自定义JWT认证转换器。 * 默认情况下Spring Security期望权限信息放在JWT的scope或scp声明中并以SCOPE_为前缀。 * 如果你的授权服务器将权限放在了其他声明例如authorities中或者你想自定义权限前缀就需要这个转换器。 * 这里我们保持默认行为但展示如何配置。 */ private JwtAuthenticationConverter jwtAuthenticationConverter() { JwtGrantedAuthoritiesConverter grantedAuthoritiesConverter new JwtGrantedAuthoritiesConverter(); // 设置权限声明在JWT中的键名默认是scope或scp grantedAuthoritiesConverter.setAuthoritiesClaimName(scope); // 设置权限前缀默认是SCOPE_。设置为null则不加前缀。 grantedAuthoritiesConverter.setAuthorityPrefix(); JwtAuthenticationConverter jwtAuthenticationConverter new JwtAuthenticationConverter(); jwtAuthenticationConverter.setJwtGrantedAuthoritiesConverter(grantedAuthoritiesConverter); return jwtAuthenticationConverter; } }这个配置类做了以下几件关键事情启用JWT资源服务器通过.oauth2ResourceServer().jwt()配置声明本服务使用JWT令牌进行保护。定义访问规则/api/public/**完全公开用于健康检查或无需认证的接口。/api/protected/**需要认证且令牌中必须包含read权限scope。hasAuthority(SCOPE_read)中的SCOPE_是Spring Security默认添加的前缀对应JWT中的scope: read。/api/admin/**需要write权限。其他所有请求anyRequest()只需认证authenticated()不检查特定权限。无状态会话SessionCreationPolicy.STATELESS确保了服务不会在服务器端创建会话完全依赖每个请求携带的JWT令牌这是RESTful API的典型做法。自定义权限映射jwtAuthenticationConverter方法展示了如何自定义从JWT声明到GrantedAuthority的转换逻辑。这是一个高级但常用的配置点特别是当你的授权服务器生成的JWT格式与Spring Security默认预期不符时。4. 实现受保护与公开的API端点配置好安全规则后我们来创建几个简单的REST控制器用于验证配置是否生效。import org.springframework.security.core.annotation.AuthenticationPrincipal; import org.springframework.security.oauth2.jwt.Jwt; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import java.util.Collections; import java.util.Map; RestController RequestMapping(/api) public class DemoResourceController { /** * 公开API无需任何令牌即可访问 */ GetMapping(/public/hello) public MapString, String publicHello() { return Collections.singletonMap(message, Hello from PUBLIC API!); } /** * 受保护的API需要有效的JWT令牌 * AuthenticationPrincipal Jwt jwt 注入当前认证的JWT对象方便获取令牌内的信息 */ GetMapping(/protected/hello) public MapString, Object protectedHello(AuthenticationPrincipal Jwt jwt) { return Map.of( message, Hello from PROTECTED API!, subject, jwt.getSubject(), // 通常为用户ID scopes, jwt.getClaimAsStringList(scope), // 获取权限范围 issuer, jwt.getIssuer() // 签发者应与配置的issuer-uri一致 ); } /** * 需要write权限的受保护API */ GetMapping(/admin/hello) public MapString, String adminHello() { return Collections.singletonMap(message, Hello from ADMIN API! You have write scope.); } }这个控制器清晰地划分了三个端点/api/public/hello公开访问用于初步测试服务是否启动。/api/protected/hello受保护端点访问它需要携带有效JWT。成功访问后会返回一些JWT中的核心信息如用户主题sub、权限范围scope等这对于调试和理解令牌内容非常有帮助。/api/admin/hello需要更高权限write的端点。5. 构建测试客户端模拟完整流程现在我们有了授权服务器端口8080和资源服务器端口8081。为了看到整个OAuth2授权码流程我们需要一个简单的客户端应用。这个客户端将模拟一个第三方Web应用引导用户去授权服务器登录获取授权码换令牌最后用令牌访问资源服务器。我们可以在同一个工程中新建一个模块或者简单起见在resources/static下创建一个HTML页面并配合一个简单的Controller来启动授权流程。这里我们选择后一种轻量级方式。5.1 客户端安全配置首先客户端需要能发起OAuth2登录。我们在application.yml中添加客户端配置注意这部分配置属于客户端理论上应放在另一个应用中这里为演示方便放在一起。# 继续在resource-server的application.yml中添加 spring: security: oauth2: client: registration: # 注册一个客户端命名为messaging-client messaging-client: provider: custom-auth-server # 指向下面定义的provider client-id: client # 必须与授权服务器中配置的client-id一致 client-secret: secret # 必须与授权服务器中配置的client-secret一致 authorization-grant-type: authorization_code # 使用授权码模式 redirect-uri: http://localhost:8081/login/oauth2/code/custom-auth-server # 回调地址 scope: read,write # 申请的权限范围 provider: # 定义一个名为custom-auth-server的提供者 custom-auth-server: # 授权服务器的基础URI issuer-uri: http://localhost:8080 # 如果授权服务器的发现端点路径不同可以手动指定 # authorization-uri: http://localhost:8080/oauth2/authorize # token-uri: http://localhost:8080/oauth2/token # user-info-uri: http://localhost:8080/userinfo # jwk-set-uri: http://localhost:8080/oauth2/jwks注意redirect-uri的格式是固定的{baseUrl}/login/oauth2/code/{registrationId}。Spring Security OAuth2 Client会自动处理这个回调端点。5.2 客户端控制器与页面创建一个控制器用于展示首页和触发OAuth2登录。import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.GetMapping; import java.security.Principal; Controller public class ClientController { GetMapping(/) public String home(Model model, Principal principal) { // 如果用户已登录principal不为null model.addAttribute(isLoggedIn, principal ! null); model.addAttribute(principalName, principal ! null ? principal.getName() : Guest); return home; // 对应 src/main/resources/templates/home.html } }然后在src/main/resources/templates下创建home.html!DOCTYPE html html langzh xmlns:thhttp://www.thymeleaf.org head meta charsetUTF-8 titleOAuth2 测试客户端/title link hrefhttps://cdn.jsdelivr.net/npm/bootstrap5.1.3/dist/css/bootstrap.min.css relstylesheet /head body classcontainer mt-5 div classcard div classcard-header h2OAuth2 授权码模式完整流程测试/h2 /div div classcard-body p th:if${isLoggedIn} 欢迎strong th:text${principalName}/strong你已成功通过OAuth2登录。 /p p th:unless${isLoggedIn} 当前状态span classtext-danger未登录/span。 /p hr div classmb-3 h5第一步获取访问令牌/h5 p点击下方按钮将跳转至授权服务器进行登录和授权。/p a th:href{/oauth2/authorization/custom-auth-server} classbtn btn-primary 前往授权服务器登录并授权 /a p classform-text text-muted small mt-2 这将触发标准的OAuth2 Authorization Code流程 /p /div div classmb-3 th:if${isLoggedIn} h5第二步使用令牌访问受保护资源/h5 p登录成功后你可以尝试访问受资源服务器保护的API。/p button onclickcallPublicApi() classbtn btn-success btn-sm访问公开API/button button onclickcallProtectedApi() classbtn btn-warning btn-sm访问受保护API (需read权限)/button button onclickcallAdminApi() classbtn btn-danger btn-sm访问管理员API (需write权限)/button div idapiResult classmt-3 p-3 border rounded stylemin-height: 100px; background-color: #f8f9fa; !-- API调用结果将显示在这里 -- /div /div div th:if${isLoggedIn} classmt-4 a th:href{/logout} classbtn btn-outline-secondary退出登录/a /div /div /div script const apiResultEl document.getElementById(apiResult); function callPublicApi() { callApi(http://localhost:8081/api/public/hello, 公开API); } function callProtectedApi() { callApi(http://localhost:8081/api/protected/hello, 受保护API); } function callAdminApi() { callApi(http://localhost:8081/api/admin/hello, 管理员API); } function callApi(url, apiName) { apiResultEl.innerHTML p调用 ${apiName} (${url}).../p; fetch(url) .then(response { if (!response.ok) { throw new Error(HTTP error! status: ${response.status}); } return response.json(); }) .then(data { apiResultEl.innerHTML pstrong${apiName} 响应成功:/strong/ppre${JSON.stringify(data, null, 2)}/pre; }) .catch(error { apiResultEl.innerHTML p classtext-dangerstrong${apiName} 调用失败:/strong ${error.message}/p; }); } /script /body /html这个页面提供了清晰的测试步骤一个按钮触发OAuth2授权码流程由Spring Security自动处理。登录成功后显示三个按钮分别用于调用资源服务器上的公开、受保护和管理员API。使用JavaScript的fetchAPI发起调用并在页面上展示结果。5.3 启用OAuth2客户端登录为了让首页的/oauth2/authorization/custom-auth-server链接生效我们需要在安全配置中启用OAuth2客户端登录。修改之前的ResourceServerConfig在SecurityFilterChain配置中增加相关规则。Configuration public class ResourceServerConfig { Bean public SecurityFilterChain resourceServerFilterChain(HttpSecurity http) throws Exception { http .oauth2ResourceServer(oauth2 - oauth2.jwt(jwt - jwt.jwtAuthenticationConverter(jwtAuthenticationConverter()))) .authorizeHttpRequests(authorize - authorize .requestMatchers(/, /login**, /webjars/**, /error**).permitAll() // 允许客户端首页和登录相关页面 .requestMatchers(/api/public/**).permitAll() .requestMatchers(/api/protected/**).hasAuthority(SCOPE_read) .requestMatchers(/api/admin/**).hasAuthority(SCOPE_write) .anyRequest().authenticated() ) // 启用OAuth2客户端登录 .oauth2Login(oauth2Login - oauth2Login .loginPage(/) // 指定登录页面为我们首页 .defaultSuccessUrl(/, true) // 登录成功后跳回首页 ) .logout(logout - logout .logoutSuccessUrl(/) // 退出后回到首页 ) .sessionManagement(session - session.sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED)) // 客户端需要Session .csrf(csrf - csrf.disable()); return http.build(); } // ... jwtAuthenticationConverter 方法保持不变 }关键改动放行路径增加了对根路径/、登录相关路径/login**等的公开访问许可。启用OAuth2登录通过.oauth2Login()配置启用客户端登录功能并指定登录页面和成功后的跳转地址。会话策略将资源服务器的无状态会话策略STATELESS改为了IF_REQUIRED。因为客户端部分需要维护用户会话存储认证后的Principal而API部分/api/**仍然通过JWT令牌进行无状态认证这两者在同一个应用内通过不同的过滤器链逻辑来管理。在更正式的微服务架构中客户端和资源服务器应拆分为两个独立应用。6. 完整流程测试与问题排查现在所有组件都已就位。请确保你的授权服务器上一篇搭建的正在localhost:8080运行然后启动本篇的资源服务器客户端集成在其中在localhost:8081。6.1 测试步骤访问客户端首页打开浏览器访问http://localhost:8081。页面应显示“未登录”状态。发起OAuth2登录点击“前往授权服务器登录并授权”按钮。浏览器会被重定向到授权服务器的登录页面http://localhost:8080/login。用户登录与授权使用你在授权服务器中配置的用户如user/password登录。登录后会看到授权确认页面询问是否允许客户端client获取read和write权限。点击“Authorize”。回调与客户端登录成功授权服务器会将授权码通过回调地址传回客户端应用。客户端应用在后台用授权码换取访问令牌和刷新令牌并建立本地会话。完成后浏览器重定向回http://localhost:8081此时页面应显示“欢迎user你已成功通过OAuth2登录。”测试API调用点击“访问公开API”应立刻成功返回{message:Hello from PUBLIC API!}。点击“访问受保护API”客户端会自动在请求头中携带获取到的访问令牌JWT访问资源服务器。资源服务器验证令牌有效且包含readscope后返回成功消息及JWT中的用户信息。点击“访问管理员API”由于我们的令牌同时拥有read和writescope所以也能成功访问。如果你在授权服务器客户端配置中只申请了readscope那么这一步会返回403 Forbidden错误。6.2 常见问题与排查技巧在实际操作中你可能会遇到一些问题。下面是一个快速排查指南问题现象可能原因排查步骤与解决方案点击登录按钮后直接跳回首页无任何反应或报错。1. 客户端配置的client-id、client-secret或redirect-uri与授权服务器中注册的不一致。2. 授权服务器的issuer-uri或端点地址不可达。1. 仔细核对application.yml中的客户端配置与授权服务器ClientRepository中的记录是否完全一致特别是redirect-uri末尾斜杠都可能导致不匹配。2. 检查授权服务器(:8080)是否正常运行。尝试直接访问http://localhost:8080/.well-known/openid-configuration看是否能返回JSON数据。登录授权后客户端页面显示已登录但调用受保护API返回401 Unauthorized。1. 资源服务器的security.oauth2.resourceserver.jwt.issuer-uri配置错误。2. JWT令牌未正确传递给资源服务器。1. 确认资源服务器的issuer-uri指向正确的授权服务器地址和端口。2. 打开浏览器开发者工具的“网络”(Network)选项卡查看调用受保护API的请求头。确认是否存在Authorization: Bearer your-jwt-token请求头。如果没有可能是客户端会话中未存储令牌或者前端JS代码的fetch请求未携带认证信息我们的示例是直接调用依赖浏览器同域会话如果跨域则需手动设置头。调用受保护API返回403 Forbidden。令牌中的权限(scope)与资源服务器要求的权限不匹配。1. 检查授权服务器颁发的令牌是否包含所需scope。可以在http://localhost:8081/api/protected/hello的成功响应中查看scopes字段。2. 检查资源服务器安全配置中的.hasAuthority(“SCOPE_xxx”)确保前缀和声明名匹配。使用我们提供的jwtAuthenticationConverter()可以灵活调整。授权服务器登录页面无法显示或报错。授权服务器自身的配置或用户服务有问题。回到授权服务器应用检查其日志。确保UserDetailsService已正确配置内存或数据库中有测试用户。控制台出现Unable to resolve Configuration with the provided Issuer错误。资源服务器启动时无法从issuer-uri获取发现文档或JWK Set。1. 网络问题确保授权服务器已启动且端口无误。2. 路径问题如果授权服务器有上下文路径(如/auth)则issuer-uri应为http://localhost:8080/auth。3. 手动指定端点如果授权服务器未实现标准发现端点可以在配置中手动指定spring.security.oauth2.resourceserver.jwt.jwk-set-uri。实操心得调试令牌当认证授权流程出现问题时解码和查看JWT令牌的内容是最高效的调试手段。你可以将获取到的access_token通常出现在客户端会话中或授权服务器的/oauth2/token端点响应里复制到在线JWT解码网站如 jwt.io 进行解码。重点关注iss签发者应与issuer-uri一致、sub用户主体、scope权限范围、exp过期时间等字段。这能帮你快速定位是令牌生成问题、令牌过期问题还是权限映射问题。7. 进阶配置与生产环境考量通过以上步骤一个基本的OAuth2认证与资源保护体系就搭建完成了。但对于生产环境还需要考虑更多因素7.1 使用公钥/私钥对替代对称密钥在之前的授权服务器配置中我们使用了MacAlgorithm.HS256对称加密。在生产环境中更推荐使用非对称加密如RSA即授权服务器用私钥签名JWT资源服务器用公钥验签。这样更安全且公钥可以安全地分发给所有资源服务器。在授权服务器端需要生成RSA密钥对并配置Bean public RegisteredClientRepository registeredClientRepository() { // ... 客户端配置 } Bean public JWKSourceSecurityContext jwkSource() { KeyPair keyPair generateRsaKey(); // 生成RSA密钥对的方法 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 (jwkSelector, securityContext) - jwkSelector.select(jwkSet); } private static KeyPair generateRsaKey() { // 使用KeyPairGenerator生成RSA密钥对 }在资源服务器端配置issuer-uri后它会自动从授权服务器的/oauth2/jwks端点获取公钥无需额外配置。7.2 令牌增强与自定义声明有时我们需要在JWT令牌中加入额外的用户信息如邮箱、角色列表等。可以在授权服务器的OAuth2TokenCustomizer中实现Bean public OAuth2TokenCustomizerJwtEncodingContext jwtCustomizer() { return context - { if (context.getTokenType().getValue().equals(“access_token”)) { Authentication principal context.getPrincipal(); // 例如从UserDetails中获取自定义信息 if (principal.getPrincipal() instanceof UserDetails userDetails) { context.getClaims().claim(“email”, “userexample.com”); context.getClaims().claim(“custom_roles”, userDetails.getAuthorities().stream() .map(GrantedAuthority::getAuthority) .collect(Collectors.toList())); } } }; }在资源服务器端可以通过注入的Jwt对象获取这些自定义声明jwt.getClaimAsString(“email”)。7.3 微服务架构下的多资源服务器在微服务中通常有多个资源服务器。最佳实践是统一的授权服务器所有微服务共享同一个授权服务器进行认证。独立的资源服务器配置每个微服务资源服务器都像本文一样配置spring-security-oauth2-resource-server和issuer-uri。网关层传递令牌API网关如Spring Cloud Gateway在将请求路由到下游微服务时必须将原始的Authorization: Bearer token请求头原封不动地传递下去。服务间调用如果一个微服务需要调用另一个微服务即服务间调用通常使用“客户端凭证”模式获取一个代表服务本身而非具体用户的令牌或者直接传递原始用户令牌需确保网络通道安全如mTLS。搭建SpringBoot Spring Security OAuth2认证体系从授权服务器到资源服务器再到客户端的完整闭环就像在搭建一套精密的门禁系统。授权服务器是签发门禁卡的中心资源服务器是各个需要刷卡进入的房间而客户端就是引导访客去中心办卡的前台。整个过程涉及配置的精确对接、令牌的生成与验证、权限的细粒度控制。我个人的体会是初期被各种配置和概念困扰是正常的最好的学习方法就是像本文这样从头到尾手动搭建一遍并利用浏览器的开发者工具和JWT解码工具亲眼观察每一个HTTP请求和响应亲手解码每一枚令牌理解数据是如何流动的。当你看到客户端成功用一枚小小的JWT令牌敲开资源服务器的大门并取回数据时那种对整个流程豁然开朗的感觉是读十篇文档也换不来的。
郑州网站建设
网页设计
企业官网