Java 如何在Spring5控制器中声明性地使用JWT授权?
有一个简单的web服务,只有一个端点Java 如何在Spring5控制器中声明性地使用JWT授权?,java,spring-boot,spring-security,jwt,spring-security-oauth2,Java,Spring Boot,Spring Security,Jwt,Spring Security Oauth2,有一个简单的web服务,只有一个端点“GET/hello” 最好在控制器中以声明的方式描述JWT,以便从中提取关于发出请求的授权用户的一些数据 在Github上浏览一些开源项目时,我发现@AuthenticationPrincipal注释不知何故参与了这个过程。然而,我找到的所有教程都没有提到这种声明性方法——它们主要展示如何创建JWT,而不是如何处理JWT。 如果你能指出我错过的值得注意的例子,我将不胜感激 很明显,这个问题很小,并且与Spring安全性的基本功能有关,但我不能把这个难题放在一
“GET/hello”
最好在控制器中以声明的方式描述JWT,以便从中提取关于发出请求的授权用户的一些数据 在Github上浏览一些开源项目时,我发现
@AuthenticationPrincipal
注释不知何故参与了这个过程。然而,我找到的所有教程都没有提到这种声明性方法——它们主要展示如何创建JWT,而不是如何处理JWT。如果你能指出我错过的值得注意的例子,我将不胜感激 很明显,这个问题很小,并且与Spring安全性的基本功能有关,但我不能把这个难题放在一起 请帮助我找到一种正确(自然)的方法,将JWT传递到控制器并从中获取数据
您能分享一个带有依赖项的工作示例和一个小测试,展示如何在controller中使用JWT吗
SpringBoot 2.4.0
import org.springframework. ??? .Jwt;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
@RestController
public class MyController {
@GetMapping("hello")
public Object getRequests(@AuthenticationPrincipal Jwt jwt) {
String name = getPropertyFromJwt(jwt, "name");
String id = getPropertyFromJwt(jwt, "id");
return Map.of("name", name, "id", id);
}
}
要成功进行身份验证,请求必须由
身份验证提供程序进行身份验证。一旦成功进行身份验证,它将返回一个身份验证
对象,该对象包含一个主体对象
@AuthenticationPrincipal
仅帮助访问此principle对象。但是,spring security没有提供一个AuthenticationProvider
,它可以通过JWT即时验证,这意味着您必须自己实现。在自定义的AuthenticationProvider
中,您验证JWT并解码感兴趣的属性,并创建一个保存这些属性的自定义主体对象,以便您可以通过@AuthenticationPrincipal
访问它们
只要快速搜索一下,就会发现这可能会对你有所帮助。深入研究后,我发现这个问题包括
三个:
如何将JWT字符串解析为对象
如何将对象传递到控制器方法中
SpingBoot中的标准/默认方法是什么
以下是简短的答案:
使用您喜欢的任何库将编码的JWT转换为对象。
其中之一是
用@AuthenticationPrincipal
注释的参数可以是任何类型的X
它来自于currentSecurityContext.getAuthorization().getPrincipal()
其中currentSecurityContext
的类型为org.springframework.security.core.context.SecurityContext
在WebFlux配置中,它来自调用ServerSecurityContextRepository.load(…)
对于每个请求(请参见下面的实现)
我没能找到#3的答案,但我意识到了这一点
这方面有几个开源的特别实现(好的和坏的)。
毕竟,我最终实现了另一个,只是为了理解陷阱
请找到一个最小工作项目示例
重点是:
- A.使用
ServerSecurityContextRepository的实现进行配置
@EnableWebFluxSecurity
public class SecurityConfig {
@Bean
SecurityWebFilterChain securityWebFilterChain(ServerHttpSecurity http) {
ServerSecurityContextRepository repo = createContextRepository();
return http
.authorizeExchange(e -> e.anyExchange().authenticated())
.securityContextRepository(repo)
.build();
}
}
- B.创建
身份验证
接口的实现和一个函数(或函数链)ServerWebExchange->Authentication
,该函数应应用于serversecuritycontextextrepository.load
方法并插入SecurityContext
(即SecurityContextImpl
)每个服务器请求的名称
- C.委托人可以是您选择的任何对象。从(B)中创建的实现方法的
Authentication.getPrincipal()
返回它
您需要的一切都在这里:如果您想按原样读取JWT(在base64中),请将HttpServletRequest添加为方法参数:(public Object getRequests(,HttpServletRequest request))并调用request.getHeader(“授权”);然后,您将使用JWT directlyanother选项直接访问标头(使用@RequestHeader注释):@RoieBeck好的,我们将该标头作为字符串。接下来,如何解析它?提供了所有java框架的列表:),maven包就是一个例子,在github页面中搜索“decodeatoken”,它非常简单。每个库都有自己的方式来解码JWT,你也可以做Base64。自己解码JWT正文(JWT的第二部分也称为有效负载:),作为一个一般规则,我认为你需要在使用它之前更好地理解JWT…谢谢Ken Chan。我相信这个例子可以指引我正确的方向。一般来说,每个应用程序都应该从头开始实现自己的AuthenticationProvider,尽管auth的各个领域都是如此标准化,您不觉得奇怪吗。我希望在SpringBoot初学者中至少能看到这个“JWT关注点”的基本实现。在我看来,对于WebFlux来说,同样的东西会带来额外的麻烦。