gpt4 book ai didi

java - 可以使用任何 JWT token 调用 API

转载 作者:行者123 更新时间:2023-11-30 10:18:29 25 4
gpt4 key购买 nike

我正在编写一个应用程序,前端用户将通过 API 调用后端。我已经实现了 JWT,用户可以在其中注册,当他们尝试登录时,他们将得到一个 JWT 作为响应,然后我可以使用 header 中的 JWT 对 API 进行其他调用。如果 JWT 不在 header 中,则调用将失败。基础知识按预期工作。我面临的问题是我可以生成自己的自定义 JWT,将其分配给 header 并能够成功调用后端。我在网上学习了很多教程,发现这个主题非常困惑,而且很难完全掌握。我毫不怀疑我的代码中缺少一些简单的东西,但我看不到什么。

这是我到目前为止所做的;

身份验证过滤器

public class JWTAuthenticationFilter extends UsernamePasswordAuthenticationFilter {

private AuthenticationManager authenticationManager;

public JWTAuthenticationFilter(AuthenticationManager authenticationManager) {
this.authenticationManager = authenticationManager;
}

@Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
try {
User credentials = new ObjectMapper().readValue(request.getInputStream(), User.class);

return authenticationManager.authenticate(
new UsernamePasswordAuthenticationToken(
credentials.getUsername(),
credentials.getPassword(),
new ArrayList<>()
)
);
} catch (IOException e) {
throw new RuntimeException(e);
}
}

@Override
protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authResult) throws IOException, ServletException {

String token = Jwts.builder()
.setSubject(((org.springframework.security.core.userdetails.User) authResult.getPrincipal()).getUsername())
.setExpiration(new Date(System.currentTimeMillis() + EXPIRATION_TIME))
.signWith(SignatureAlgorithm.HS512, SECRET.getBytes())
.compact();
response.addHeader(HEADER_STRING, TOKEN_PREFIX + token);

}
}

授权过滤器

public class JWTAuthorizationFilter extends BasicAuthenticationFilter     {

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

@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {
String header = request.getHeader(HEADER_STRING);

if(StringUtils.isBlank(header) || ! StringUtils.startsWith(header, TOKEN_PREFIX)){
chain.doFilter(request, response);
return;
}

UsernamePasswordAuthenticationToken authenticationToken = getAuthentication(request);

SecurityContextHolder.getContext().setAuthentication(authenticationToken);
chain.doFilter(request, response);
}

private UsernamePasswordAuthenticationToken getAuthentication(HttpServletRequest request) {
String token = request.getHeader(HEADER_STRING);

if(StringUtils.isNotBlank(token)){
String user = Jwts.parser()
.setSigningKey(SECRET.getBytes())
.parseClaimsJws(token.replace(TOKEN_PREFIX, ""))
.getBody()
.getSubject();

if(StringUtils.isNotBlank(user)){
return new UsernamePasswordAuthenticationToken(user, null, new ArrayList<>());
}

return null;
}

return null;
}
}

网络安全

@EnableWebSecurity
public class WebSecurity extends WebSecurityConfigurerAdapter {

private UserDetailsService userDetailsService;
private BCryptPasswordEncoder bCryptPasswordEncoder;

public WebSecurity(UserDetailsService userDetailsService, BCryptPasswordEncoder bCryptPasswordEncoder) {
this.userDetailsService = userDetailsService;
this.bCryptPasswordEncoder = bCryptPasswordEncoder;
}

@Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity.cors().and().csrf().disable().authorizeRequests()
.antMatchers(HttpMethod.POST, SIGN_UP_URL).permitAll()
.anyRequest().authenticated()
.and()
.addFilter(new JWTAuthenticationFilter(authenticationManager()))
.addFilter(new JWTAuthorizationFilter(authenticationManager()))
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
}

@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(bCryptPasswordEncoder);
}

@Bean
CorsConfigurationSource corsConfigurationSource(){
final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", new CorsConfiguration().applyPermitDefaultValues());
return source;
}
}

正如我所说,我发现这个主题相当困难,所以我确信我的代码中可能存在简单的错误。如果您能以任何方式帮助或阐明我的问题,将不胜感激

最佳答案

这似乎是检查 JWT 的 servlet 过滤器的关键代码:

String token = request.getHeader(HEADER_STRING);

if (StringUtils.isNotBlank(token)){
String user = Jwts.parser()
.setSigningKey(SECRET.getBytes())
.parseClaimsJws(token.replace(TOKEN_PREFIX, ""))
.getBody()
.getSubject();

if (StringUtils.isNotBlank(user)){
return new UsernamePasswordAuthenticationToken(user, null, new ArrayList<>());
}

如果仔细观察您正在做的事情,您会发现您的逻辑是从 JWT 中提取主题。这一点是正确的。但是只要主题不为空,您就会授权该用户。换句话说,任何用户都将被您当前的逻辑授权。相反,您通常会这样做:

if (StringUtils.isNotBlank(user)){
// check that user against a database/cache
// if the account is active etc. THEN authorize the user
}

通常,在从 JWT 中提取主题/用户名后,您将访问数据库/缓存以检查该用户的帐户是否仍处于 Activity 状态。如果不是,那么您将向调用应用程序返回 401。 JWT 本身并不意味着用户已获得授权,因为在某些时候您可能会撤销该用户的 token , token 可能会过期等。

关于java - 可以使用任何 JWT token 调用 API,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49221342/

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