gpt4 book ai didi

java - 如何为整个Spring Boot应用程序生成 token

转载 作者:行者123 更新时间:2023-12-02 02:39:09 27 4
gpt4 key购买 nike

我有一个 REST API,它使用外部 API。我正在使用 WebClient,但我必须将每个请求传递给外部 API 的 token 。该 token 是通过 addAuthentication POST 调用生成的。我想在整个应用程序中使用相同的 token ,直到它过期为止;这是一个特定于应用程序的 token 。但我不确定如何生成在我的整个应用程序中可用的 token ,以便在所有 http 请求中使用。

我尝试实例化一个连接器类并在我的 Spring Boot 应用程序类中的 @PostConstruct 中使用;但我不确定如何在所有应用程序中访问此实例。

   @Component
public class AppConnector {
@Value("${some.dev.url}")
private String baseUrl;
@Value("${some.dev.appid}")
private String appId;
@Value("${some.dev.username}")
private String username;
@Value("${some.dev.password}")
private String password;
private String token;
private boolean isConnected;
private final WebClient webClient;


@Autowired
public AppConnector(WebClient webClient) {
this.webClient = WebClient.builder()
.baseUrl("http://localhost:8080/api")
.defaultHeader("application-id", "client-01")
.defaultHeader("username", username)
.defaultHeader("password", password)
.build();
}

/***
* Method to add Authentication
* @return Session_Token: String
*/
public String addAuthentication() {

AddAuthenticationOutputVO response = null;
response = this.webClient.post()
.uri("/authentication?version=1.0")
.retrieve()
.bodyToMono(AddAuthenticationOutputVO.class).block();

this.token = response.getSession_token();
return response.getSession_token();
}

}

最佳答案

一种解决方案是使用由主应用程序签名和发布的 JWT,并且两个系统都必须拥有主 key secret 。验证可以是简单的 token 验证,您可以在 JWT 中找到 userId 或 userName。过期时间位于 JWT 内部,因此每次验证 token 时,系统都可以知道 token 是否已过期,并且您可以将过期 token 回复给客户端。

这个使用 Spring 的解决方案是实现两个过滤器,用于生成 token 的身份验证和用于验证 token 的授权。

这是示例代码。

身份验证:

public class JWTAuthenticationFilter extends UsernamePasswordAuthenticationFilter {

private final AuthenticationManager authenticationManager;
private final String maxSizeToUpload;

public JWTAuthenticationFilter(AuthenticationManager authenticationManger, String maxSizeToUpload) {
this.authenticationManager = authenticationManger;
this.maxSizeToUpload = maxSizeToUpload;
}

@Override
public Authentication attemptAuthentication(HttpServletRequest request,
HttpServletResponse response) throws AuthenticationException {
try {
AuthenticationRequest authRequest = new ObjectMapper().readValue(request.getInputStream(),
AuthenticationRequest.class);
return authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(
authRequest.getUsername(), authRequest.getPassword(), new ArrayList<>()));
} catch (IOException e) {
throw new RuntimeException(e);
}
}

@Override
protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response,
FilterChain chain, Authentication auth) throws IOException, ServletException {
// Los tokens son generados hasta el final del día.
Date expirationDate = DateUtil.setZeroHour(DateUtil.getDateAddDays(new Date(), 1));

String token = Jwts.builder().setIssuedAt(new Date()).setIssuer(WebSecurity.ISSUER)
.setSubject(((BuserDetails)auth.getPrincipal()).getUsername())
.setExpiration(expirationDate)
.signWith(SignatureAlgorithm.HS512, HardCodeUtil.JWT_KEY).compact();
response.addHeader(WebSecurity.HEADER_AUTHORIZATION, WebSecurity.PREFIX_JWT + token);
response.addHeader(WebSecurity.HEADER_JWT_EXPIRATION_DATE, String.valueOf(expirationDate.getTime()));
ObjectMapper mapper = new ObjectMapper();
ExtraParams extraParams = new ExtraParams(
((BuserDetails)auth.getPrincipal()).getBuser().getBusiness().getCurrency(),
Byte.parseByte(maxSizeToUpload.replace("MB", "")));
String body = mapper.writeValueAsString(new LoginResponse(((BuserDetails)auth.getPrincipal()).getBuser(),
extraParams));
response.setContentType("application/json");
response.getWriter().write(body);
response.getWriter().flush();
response.getWriter().close();
}

}

授权:

这必须在两个系统中使用,您可以找到我使用的 JWT_KEY,您需要在两个系统中共享该值。

public class JWTAuthorizationFilter extends BasicAuthenticationFilter {

private static final Logger log = Logger.getLogger(JWTAuthorizationFilter.class.getName());

public JWTAuthorizationFilter(AuthenticationManager authManager) {
super(authManager);
}

@Override
protected void doFilterInternal(HttpServletRequest req, HttpServletResponse res, FilterChain chain)
throws IOException, ServletException {
String header = req.getHeader(WebSecurity.HEADER_AUTHORIZATION);
if (header == null || !header.startsWith(WebSecurity.PREFIX_JWT)) {
chain.doFilter(req, res);
return;
}
try {
UsernamePasswordAuthenticationToken authentication = getAuthentication(req);
SecurityContextHolder.getContext().setAuthentication(authentication);
chain.doFilter(req, res);
}catch (SignatureException ex) {
log.log(Level.SEVERE, "FIRMA INVALIDA DEL JWT ENVIADO");
}catch (MalformedJwtException ex) {
log.log(Level.SEVERE, "ESTRUCTURA INVALIDA DEL JWT ENVIADO");
}catch (ExpiredJwtException ex) {
GeneralResponse jwtInvalidResponse = new GeneralResponse(ErrorsEnum.JWT_EXPIRED);
ObjectMapper mapper = new ObjectMapper();
String body = mapper.writeValueAsString(jwtInvalidResponse);
res.setContentType("application/json");
res.getWriter().write(body);
res.getWriter().flush();
res.getWriter().close();
}catch (UnsupportedJwtException ex) {
log.log(Level.SEVERE, "NO SOPORTADO JWT ENVIADO");
}catch (IllegalArgumentException ex) {
log.log(Level.SEVERE, "ILLEGAL ARGUMENT JWT ENVIADO");
}
}

private UsernamePasswordAuthenticationToken getAuthentication(HttpServletRequest request) {
String token = request.getHeader(WebSecurity.HEADER_AUTHORIZATION);
if (token != null) {
String user = Jwts.parser()
.setSigningKey(HardCodeUtil.JWT_KEY)
.parseClaimsJws(token.replace(WebSecurity.PREFIX_JWT, ""))
.getBody()
.getSubject();
if (user != null) {
return new UsernamePasswordAuthenticationToken(user, null, new ArrayList<>());
}
}
return null;
}

}

在我用这个库实现的示例中:

<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.1</version>
</dependency>

关于java - 如何为整个Spring Boot应用程序生成 token ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57190060/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com