相关疑难解决方法(0)

如何获取活动用户的UserDetails

在我的控制器中,当我需要活动(登录)用户时,我正在执行以下操作来获取我的UserDetails实现:

User activeUser = (User)SecurityContextHolder.getContext().getAuthentication().getPrincipal();
log.debug(activeUser.getSomeCustomField());
Run Code Online (Sandbox Code Playgroud)

它工作正常,但我认为Spring可以在这样的情况下让生活更轻松.有没有办法将UserDetails自动装配到控制器或方法?

例如,类似于:

public ModelAndView someRequestHandler(Principal principal) { ... }
Run Code Online (Sandbox Code Playgroud)

但是,而不是得到UsernamePasswordAuthenticationToken,我得到了一个UserDetails

我正在寻找一个优雅的解决方案.有任何想法吗?

java spring spring-mvc spring-security

165
推荐指数
6
解决办法
12万
查看次数

将 JWT 身份验证主体转换为 Spring 中更可用的内容

我有一个 Spring Boot 微服务,用于验证 JWT(由不同服务颁发)进行身份验证。它运行良好,我可以像这样访问控制器中的 JWT 详细信息:

// build.gradle
implementation 'org.springframework.boot:spring-boot-starter-oauth2-resource-server'

// MyController.java
@RestController
@RequestMapping("/")
public class MyController {
    @GetMapping()
    public String someControllerMethod(@AuthenticationPrincipal Jwt jwt) {
        int userId = Integer.parseInt(jwt.getClaim("userid"));
        ...
    }
}
Run Code Online (Sandbox Code Playgroud)

效果很好。我可以从 JWT 中提取我需要的内容,然后使用正确的用户 ID 等继续与我的数据库对话。

然而,我发现必须使用 Jwt 类型在每个控制器中获取这些值有点乏味。有没有办法可以注入不同的类型作为@AuthenticationPrincipal?

例如,我自己的类已经从 JWT 中提取了所需的内容,并公开了类似.getUserId()返回 int 的内容?这也让我可以集中解析声明或抛出异常(如果它们不符合预期)的逻辑。

更新

经过更多谷歌洞穴探险后,似乎我有两个选择

选项1:@ControllerAdvice和@ModelAttribute

正如这个答案中所解释的。我可以做类似的事情:

import com.whatever.CustomPrincipal; // a basic "data" class with some properties, getters, setters and constructor
import org.springframework.security.core.Authentication;
import org.springframework.security.oauth2.jwt.Jwt;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ModelAttribute;

@ControllerAdvice
public class SecurityControllerAdvice { …
Run Code Online (Sandbox Code Playgroud)

spring spring-security spring-boot

7
推荐指数
1
解决办法
9041
查看次数

Spring Security:为什么身份验证扩展主体?

Spring Security假设Authentication是主体。

public interface Authentication extends Principal, Serializable {}
Run Code Online (Sandbox Code Playgroud)

HttpServletRequest具有getUserPrincipal方法,该方法负责访问主体对象。

让我们考虑这种情况:

public interface RealPrincipal extends Principal {
   public Integer getId();
}
Run Code Online (Sandbox Code Playgroud)

通用模块A具有Real Principal接口和实现。

模块A使用通用模块A,Servlet Api,并且不依赖于Spring Security:

模块B使用通用模块A,Servlet Api并配置Spring Security。该模块负责安全性和UserDetails的实现。

Web A使用模块A和模块B。

为了使用请求方法,我最终得到了这样的实现:

public ModelAndView someRequestHandler(Principal principal) {
   User activeUser = (User) ((Authentication) principal).getPrincipal();
   ...
}
Run Code Online (Sandbox Code Playgroud)

这迫使我必须对模块A和其他模块依赖Spring Security。我相信适当的servlet api抽象不应依赖于spring安全性。request.getUserPrincipal应该返回真实的主体。

请解释为什么org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestWrapper返回

验证而不是Real Principal

编辑:我已将通用模块A添加到我的方案,并更新了模块B负责安全性。

spring spring-security

5
推荐指数
1
解决办法
3053
查看次数

Spring MVC 如何为控制器方法提供可注入性

Spring MVC 控制器方法接受在调用方法之前注入的不同参数。像HttpServletRequestHttpServletResponsejava.security.Principal等等。

@RequestMapping("/test")
public String test(HttpServletRequest req, Principal user){}
Run Code Online (Sandbox Code Playgroud)

如何声明可以在 controlelr 方法中注入的内容?

@RequestMapping("/test")
public String test(MyCustomInjectable myInjectable){}
Run Code Online (Sandbox Code Playgroud)

关于具体案例的更多信息:

我想HttpServletRequest在一些 servlet 过滤器中解析并构造一个将在控制器方法中使用的对象。更准确地说,我将解析 JWT 令牌并访问声明。

java spring dependency-injection spring-mvc spring-boot

5
推荐指数
1
解决办法
1342
查看次数