我为spring安全配置了jwt auth provider。下面是SecurityConfig.java
@Configuration
@EnableWebSecurity
@EnableMethodSecurity
public class SecurityConfig {
private final UserDetailsServiceImpl userDetailsService;
private final AuthEntryPointJwt unauthorizedHandler;
public SecurityConfig(UserDetailsServiceImpl userDetailsService, AuthEntryPointJwt unauthorizedHandler) {
this.userDetailsService = userDetailsService;
this.unauthorizedHandler = unauthorizedHandler;
}
@Bean
public AuthTokenFilter authenticationJwtTokenFilter() {
return new AuthTokenFilter();
}
@Bean
public DaoAuthenticationProvider authenticationProvider() {
DaoAuthenticationProvider authProvider = new DaoAuthenticationProvider();
authProvider.setUserDetailsService(userDetailsService);
authProvider.setPasswordEncoder(passwordEncoder());
return authProvider;
}
@Bean
public AuthenticationManager authenticationManager(AuthenticationConfiguration authConfig) throws Exception {
return authConfig.getAuthenticationManager();
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
return http.csrf(AbstractHttpConfigurer::disable)
.exceptionHandling(exception -> exception.authenticationEntryPoint(unauthorizedHandler))
.sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
.authorizeHttpRequests(auth ->
auth.requestMatchers("/auth/**").permitAll()
.requestMatchers("/api/**").authenticated()
.anyRequest().authenticated()
).addFilterBefore(authenticationJwtTokenFilter(), UsernamePasswordAuthenticationFilter.class)
.authenticationProvider(authenticationProvider())
.build();
}
@Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurer() {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("*")
.allowedMethods("GET", "POST", "PUT", "DELETE", "PATCH", "OPTIONS")
.allowedHeaders("*")
.allowCredentials(false)
.maxAge(3600);
}
};
}
}
字符串
正如你所看到的,我已经允许了匹配/auth/**
的请求。但是这些端点无论如何都返回401。
我的授权控制器
@RestController
@RequestMapping("/auth")
public class AuthController {
private final AuthenticationManager authenticationManager;
private final UserRepository userRepository;
private final PasswordEncoder encoder;
private final JwtUtils jwtUtils;
public AuthController(AuthenticationManager authenticationManager, UserRepository userRepository, PasswordEncoder encoder, JwtUtils jwtUtils) {
this.authenticationManager = authenticationManager;
this.userRepository = userRepository;
this.encoder = encoder;
this.jwtUtils = jwtUtils;
}
@PostMapping("/signin")
public ResponseEntity<?> authenticateUser(@Valid @RequestBody LoginRequest loginRequest) {
Authentication authentication = authenticationManager
.authenticate(new UsernamePasswordAuthenticationToken(loginRequest.getUsername(), loginRequest.getPassword()));
SecurityContextHolder.getContext().setAuthentication(authentication);
UserDetailsImpl userDetails = (UserDetailsImpl) authentication.getPrincipal();
ResponseCookie jwtCookie = jwtUtils.generateJwtCookie(userDetails);
return ResponseEntity.ok().header(HttpHeaders.SET_COOKIE, jwtCookie.toString())
.body(new UserInfoResponse(userDetails.getId(),
userDetails.getUsername(),
userDetails.getEmail()));
}
@PostMapping("/signup")
public ResponseEntity<?> registerUser(@Valid @RequestBody SignupRequest signUpRequest) {
if (userRepository.existsByUsername(signUpRequest.getUsername())) {
return ResponseEntity.badRequest().body("Error: Username is already taken!");
}
if (userRepository.existsByEmail(signUpRequest.getEmail())) {
return ResponseEntity.badRequest().body("Error: Email is already in use!");
}
// Create new user's account
User user = new User(signUpRequest.getUsername(),
signUpRequest.getEmail(),
encoder.encode(signUpRequest.getPassword()));
userRepository.save(user);
return ResponseEntity.ok("User registered successfully!");
}
@PostMapping("/signout")
public ResponseEntity<?> logoutUser() {
ResponseCookie cookie = jwtUtils.getCleanJwtCookie();
return ResponseEntity.ok().header(HttpHeaders.SET_COOKIE, cookie.toString())
.body("You've been signed out!");
}
}
@Data
@AllArgsConstructor
@NoArgsConstructor
class SignupRequest {
private String username;
private String email;
private String password;
}
@Data
@AllArgsConstructor
@NoArgsConstructor
class LoginRequest {
private String username;
private String password;
}
@Data
@AllArgsConstructor
@NoArgsConstructor
class UserInfoResponse {
private Long id;
private String username;
private String email;
}
型
有人能帮我找出我做错了什么吗?
=更新=
这是我的AuthTokenFilter
@Service
public class AuthTokenFilter extends OncePerRequestFilter {
@Autowired
private JwtUtils jwtUtils;
@Autowired
private UserDetailsServiceImpl userDetailsService;
private static final Logger logger = LoggerFactory.getLogger(AuthTokenFilter.class);
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
try {
String jwt = parseJwt(request);
if (jwt != null && jwtUtils.validateJwtToken(jwt)) {
String username = jwtUtils.getUserNameFromJwtToken(jwt);
UserDetails userDetails = userDetailsService.loadUserByUsername(username);
UsernamePasswordAuthenticationToken authentication =
new UsernamePasswordAuthenticationToken(userDetails,
null,
userDetails.getAuthorities());
authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
SecurityContextHolder.getContext().setAuthentication(authentication);
}
} catch (Exception e) {
logger.error("Cannot set user authentication: {}", e);
}
filterChain.doFilter(request, response);
}
private String parseJwt(HttpServletRequest request) {
return request.getHeader(HttpHeaders.AUTHORIZATION);
}
}
型
2条答案
按热度按时间toiithl61#
对于springboot 3.1.1,你可以参考下面的安全代码:
字符串
CustomAuthenticationManager:
型
nkoocmlb2#
为经过身份验证的端点添加请求匹配器,并允许任何其他请求工作。
字符串
这很奇怪基本上,
anyRequest().authenticated()
在最后覆盖了permitAll
的请求匹配器。因此,决定为经过身份验证的端点添加匹配器,并允许其他所有操作。
如果你认为这不是一个最佳的解决方案,请随时发表你的想法和替代解决方案