gpt4 book ai didi

spring-boot - Spring Security - 获取登录页面时,安全性尝试进行身份验证并返回 401 错误

转载 作者:行者123 更新时间:2023-12-04 09:37:26 25 4
gpt4 key购买 nike

我正在开发具有微服务架构的 Spring Boot 应用程序。我正在使用 JWT 身份验证。
1-http://localhost:8762/auth {"username":"admin", "password":"12345"}(POST 请求)
2-http://localhost:8762/auth/loginPage(获取页面请求)
当我尝试第一个请求时,身份验证运行良好,我获得登录信息和 jwt token 。
但是当我尝试获取登录页面的第二个请求时,spring 正在尝试进行身份验证并返回 401 错误。
如何忽略登录页面的身份验证。
我有 zull 项目作为网关和身份验证项目作为 auth。

if(header == null || !header.startsWith(jwtConfig.getPrefix())) {
chain.doFilter(request, response); // If not valid, go to the next filter.
return;
}
我认为此时,我必须覆盖过滤器。但我不知道我如何编写过滤器。
这是我的身份验证代码。
身份验证项目 -> WebSecurityConfigurerAdapter
@EnableWebSecurity
public class SecurityCredentialsConfig extends WebSecurityConfigurerAdapter {

@Autowired
private JwtConfig jwtConfig;

@Autowired
private UserDetailsService userDetailsService;

@Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
// make sure we use stateless session; session won't be used to store user's state.
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
// handle an authorized attempts
.exceptionHandling().authenticationEntryPoint((req, rsp, e) -> rsp.sendError(HttpServletResponse.SC_UNAUTHORIZED))
.and()
// Add a filter to validate user credentials and add token in the response header

// What's the authenticationManager()?
// An object provided by WebSecurityConfigurerAdapter, used to authenticate the user passing user's credentials
// The filter needs this auth manager to authenticate the user.
.addFilter(new JwtUsernameAndPasswordAuthenticationFilter(authenticationManager(), jwtConfig()))
.authorizeRequests()
// allow all POST requests
.antMatchers("/auth/**").permitAll()
.antMatchers("/user/register").permitAll()
// any other requests must be authenticated
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/auth/loginPage");
}

// Spring has UserDetailsService interface, which can be overriden to provide our implementation for fetching user from database (or any other source).
// The UserDetailsService object is used by the auth manager to load the user from database.
// In addition, we need to define the password encoder also. So, auth manager can compare and verify passwords.
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(new BCryptPasswordEncoder());
}

@Bean
public JwtConfig jwtConfig() {
return new JwtConfig();
}
}
auth -> UsernamePasswordAuthenticationFilter
public class JwtUsernameAndPasswordAuthenticationFilter extends UsernamePasswordAuthenticationFilter {


private AuthenticationManager authManager;

private final JwtConfig jwtConfig;

public JwtUsernameAndPasswordAuthenticationFilter(AuthenticationManager authManager, JwtConfig jwtConfig) {
this.authManager = authManager;
this.jwtConfig = jwtConfig;

// By default, UsernamePasswordAuthenticationFilter listens to "/login" path.
// In our case, we use "/auth". So, we need to override the defaults.
//this.setRequiresAuthenticationRequestMatcher(new AntPathRequestMatcher(jwtConfig.getUri(), "POST"));

this.setRequiresAuthenticationRequestMatcher(new OrRequestMatcher(
new AntPathRequestMatcher("/auth/**")
, new AntPathRequestMatcher("/user/register")
));
}

@Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response)
throws AuthenticationException {

try {

// 1. Get credentials from request
UserDTO creds = new ObjectMapper().readValue(request.getInputStream(), UserDTO.class);

// 2. Create auth object (contains credentials) which will be used by auth manager
UsernamePasswordAuthenticationToken authToken = new UsernamePasswordAuthenticationToken(
creds.getUsername(), creds.getPassword(), Collections.emptyList());

// 3. Authentication manager authenticate the user, and use UserDetialsServiceImpl::loadUserByUsername() method to load the user.
return authManager.authenticate(authToken);

} catch (IOException e) {
throw new RuntimeException(e);
}
}

// Upon successful authentication, generate a token.
// The 'auth' passed to successfulAuthentication() is the current authenticated user.
@Override
protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain,
Authentication auth) throws IOException, ServletException {
Long now = System.currentTimeMillis();
String token = Jwts.builder()
.setSubject(auth.getName())
// Convert to list of strings.
// This is important because it affects the way we get them back in the Gateway.
.claim("authorities", auth.getAuthorities().stream()
.map(GrantedAuthority::getAuthority).collect(Collectors.toList()))
.setIssuedAt(new Date(now))
.setExpiration(new Date(now + jwtConfig.getExpiration() * 1000)) // in milliseconds
.signWith(SignatureAlgorithm.HS512, jwtConfig.getSecret().getBytes())
.compact();

// Add token to header
response.addHeader(jwtConfig.getHeader(), jwtConfig.getPrefix() + token);
}
}
Controller
@GetMapping("/auth/loginPage")
public String loginPage() {
return "login";
}

最佳答案

我认为您的问题在 JwtUsernameAndPasswordAuthenticationFilter您也已注释掉这一点。您正在 POST 上触发此过滤器和 GET .您只想为 POST 触发它。
当前方法

            this.setRequiresAuthenticationRequestMatcher(new OrRequestMatcher(                                                                                     
new AntPathRequestMatcher("/auth/**")
, new AntPathRequestMatcher("/user/register")
));
更新
            this.setRequiresAuthenticationRequestMatcher(new OrRequestMatcher(                                                                                     
new AntPathRequestMatcher("/auth/**", "POST")
, new AntPathRequestMatcher("/user/register", "POST")
));

关于spring-boot - Spring Security - 获取登录页面时,安全性尝试进行身份验证并返回 401 错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62504015/

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