所以我尝试使用JWT实现一个注册和登录机制。但是,尽管在安全配置中使用了permitAll(),但当未经身份验证的用户尝试访问“/user/register”时,它仍然返回401
这里是UserServiceImpl.java
package com.kelompok7.bukuku.user;
import com.kelompok7.bukuku.user.role.ERole;
import com.kelompok7.bukuku.user.role.Role;
import com.kelompok7.bukuku.user.verificationToken.VerificationToken;
import com.kelompok7.bukuku.user.verificationToken.VerificationTokenRepo;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import javax.transaction.Transactional;
import java.io.UnsupportedEncodingException;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
@Service @RequiredArgsConstructor @Transactional @Slf4j
public class UserServiceImpl implements UserService, UserDetailsService {
@Autowired
private final UserRepo userRepo;
@Autowired
private final VerificationTokenRepo verificationTokenRepo;
@Autowired
private JavaMailSender mailSender;
@Bean
public PasswordEncoder encoder() {
return new BCryptPasswordEncoder();
}
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
User user = userRepo.findByUsername(username);
if(user == null){
log.error("{}", SecurityContextHolder.getContext().toString());
log.error("User not found in the database");
throw new UsernameNotFoundException("User not found in the database");
}
else{
log.info("User found in the database: {}", username);
}
Collection<SimpleGrantedAuthority> authorities = user.getAuthorities();
return new org.springframework.security.core.userdetails.User(user.getUsername(), user.getPassword(), authorities);
}
@Override
public User register(User user) throws MessagingException, UnsupportedEncodingException {
log.info("Saving new user {} to the database", user.getName());
user.setPassword(encoder().encode(user.getPassword()));
Set<Role> role = new HashSet<>();
role.add(new Role(ERole.ROLE_USER));
user.setRoles(role);
user.setEnabled(false);
userRepo.save(user);
return user;
}
}
这里是UserController.java
package com.kelompok7.bukuku.user;
import lombok.RequiredArgsConstructor;
import org.springframework.data.repository.query.Param;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.\*;
import org.springframework.web.servlet.support.ServletUriComponentsBuilder;
import javax.mail.MessagingException;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.util.List;
import java.util.Optional;
@RestController
@RequestMapping("/user")
@RequiredArgsConstructor
public class UserController {
private final UserService userService;
@PostMapping("/register")
public ResponseEntity<User> register(@RequestBody User user) throws MessagingException, UnsupportedEncodingException {
URI uri = URI.create(ServletUriComponentsBuilder.fromCurrentContextPath().path("user/register").toUriString());
return ResponseEntity.created(uri).body(userService.register(user));
}
}
这里是SecurityConfiguration.java
package com.kelompok7.bukuku.security;
import com.nimbusds.jose.jwk.JWK;
import com.nimbusds.jose.jwk.JWKSet;
import com.nimbusds.jose.jwk.RSAKey;
import com.nimbusds.jose.jwk.source.ImmutableJWKSet;
import com.nimbusds.jose.jwk.source.JWKSource;
import com.nimbusds.jose.proc.SecurityContext;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.Customizer;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityCustomizer;
import org.springframework.security.config.annotation.web.configurers.oauth2.server.resource.OAuth2ResourceServerConfigurer;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.oauth2.jwt.JwtDecoder;
import org.springframework.security.oauth2.jwt.JwtEncoder;
import org.springframework.security.oauth2.jwt.NimbusJwtDecoder;
import org.springframework.security.oauth2.jwt.NimbusJwtEncoder;
import org.springframework.security.web.SecurityFilterChain;
@Configuration
@EnableWebSecurity
@RequiredArgsConstructor
public class SecurityConfiguration {
@Autowired
private final RsaKeyProperties rsaKeys;
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
return http
.csrf(csrf -> csrf.disable())
.cors(cors -> cors.disable())
.authorizeRequests(auth -> auth
.antMatchers("/**").permitAll()
.anyRequest().permitAll()
)
.oauth2ResourceServer(OAuth2ResourceServerConfigurer::jwt)
.sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
.httpBasic(Customizer.withDefaults())
.build();
}
// @Bean
// public WebSecurityCustomizer webSecurityCustomizer() {
// return (web) -\> web.ignoring()
// .antMatchers("/\*\*");
// }
@Bean
JwtDecoder jwtDecoder(){
return NimbusJwtDecoder.withPublicKey(rsaKeys.publicKey()).build();
}
@Bean
JwtEncoder jwtEncoder(){
JWK jwk = new RSAKey.Builder(rsaKeys.publicKey()).privateKey(rsaKeys.privateKey()).build();
JWKSource<SecurityContext> jwks = new ImmutableJWKSet<>(new JWKSet(jwk));
return new NimbusJwtEncoder(jwks);
}
}
最后是日志
2022-11-03 16:15:29.525 ERROR 19358 --- [nio-8081-exec-2] c.kelompok7.bukuku.user.UserServiceImpl : SecurityContextImpl [Null authentication]
2022-11-03 16:15:29.525 ERROR 19358 --- [nio-8081-exec-2] c.kelompok7.bukuku.user.UserServiceImpl : User not found in the database
我希望请求会通过并被处理,但它似乎被SecurityFilterChain捕获并得到401 Unauthorized。我尝试禁用CSRF和CORS,但仍然失败。我甚至刚刚将permitAll()设置为anyRequest,但不知何故仍然得到401。
唯一可行的方法似乎是使用webSecurityCustomizer和web.ignoring(),但我读到它将完全跳过securityFilterChain,所以我不确定它是否安全。它安全吗?它通常是这样做的吗?有没有更好的方法?
另外,即使web.ignoring()有效,我也想知道为什么permitAll()不起作用。这是正常的吗?
谢谢你的回答
2条答案
按热度按时间hec6srdp1#
您是否尝试过在antmatcher中提供完整路径
?
2ekbmq322#
我真的很抱歉,但事实证明,这是由于我的愚蠢的错误,包括授权在请求时,我不应该。
我最初的要求是:
它应该是什么,以及工作:
getContext()仍然返回空的身份验证,但permitAll()工作正常,所以我猜这是正常的行为。这整个时间我怀疑这是不是原因,所以我花了很多天试图解决它没有用。
我很感激你的帮助谢谢。