我有一个 Spring Boot 微服务应用程序。我有一个要求,
- 如果通过 Controller 调用方法(即某些用户点击 API),则响应应该是登录用户的用户名。
- 如果从任何非 Controller (例如计划任务、异步方法等)调用方法,则响应应该是默认用户,即系统。
所以,我有一个 UserDetailService 方法,我想在其中编写此逻辑。
@Service
public class UserDetailsService
{
@Autowired
WebClient.Builder webClientBuilder;
@Autowired
HttpServletRequest request;
@Value("${common.serverurl}")
private String reqUrl;
public UserReturnData getCurrentUser()
{
if (request == null)
{
UserReturnData userDetails = new UserReturnData();
userDetails.setId((long) 404);
userDetails.setUsername("system");
return userDetails;
} else
{
UserReturnData userDetails = webClientBuilder.build().get().uri(reqUrl + "user/me")
.header("Authorization", request.getHeader("Authorization")).retrieve()
.bodyToMono(UserReturnData.class).block();
return userDetails;
}
}
}
为了检查方法是否从 Controller 触发,我自动连接 HttpServletRequest 并将其与 null 进行比较。 但是,当从异步服务触发此操作时,它会抛出异常“您是否指的是实际 Web 请求之外的请求属性”
是否有其他方法可以确定该方法从何处触发。逻辑很简单,如果涉及 Controller ,即如果涉及某些 API 调用,则返回登录用户,否则返回默认用户。
最佳答案
SecurityContextHolder可用于检查当前线程是否与登录用户关联。以下方法演示了使用方法。
public String getCurrentUser() {
String userName="SYSTEM";
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
if (authentication!=null && !(authentication instanceof AnonymousAuthenticationToken)) {
userName = authentication.getName();
}
return userName;
}
由@Sridhar Patnaik 贡献。引用R.G.的评论,按以下方式处理
- 删除了 Autowiring 的 HttpServletRequest
- 已创建请求变量 HttpServletRequest 请求 = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()) .getRequest();
- 为请求添加了空检查。因此,如果涉及 Controller ,请求将不为空,并且将返回登录用户。否则,系统用户将被返回
@Service
public class UserDetailsService
{
@Autowired
WebClient.Builder webClientBuilder;
/*
* @Autowired HttpServletRequest request;
*/
@Value("${common.serverurl}")
private String reqUrl;
public UserReturnData getCurrentUser() throws Exception
{
try
{
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes())
.getRequest();
if (request == null)
{
UserReturnData userDetails = new UserReturnData();
userDetails.setId((long) 404);
userDetails.setUsername("system");
return userDetails;
}
else
{
UserReturnData userDetails = webClientBuilder.build().get().uri(reqUrl + "user/me")
.header("Authorization", request.getHeader("Authorization")).retrieve()
.bodyToMono(UserReturnData.class).block();
return userDetails;
}
} catch (Exception e)
{
throw new Exception("Something Went Wrong !");
}}
关于java - Spring Boot 2 - 识别方法是通过 Controller 还是异步服务触发,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65838291/