首先,昨天我使它工作,以便我可以注册,接收一个验证邮件,并单击邮件中的链接,使帐户+我能够登录和接收一个令牌。今天,我尝试实现JWT验证,但是当在postman中输入注册细节时,我得到了下一个错误:
java.lang.IllegalArgumentException: JWT String argument cannot be null or empty.
at io.jsonwebtoken.lang.Assert.hasText(Assert.java:132) ~[jjwt-api-0.11.5.jar:0.11.5]
at io.jsonwebtoken.impl.DefaultJwtParser.parse(DefaultJwtParser.java:527) ~[jjwt-impl-0.11.5.jar:0.11.5]
at io.jsonwebtoken.impl.DefaultJwtParser.parseClaimsJws(DefaultJwtParser.java:589) ~[jjwt-impl-0.11.5.jar:0.11.5]
at io.jsonwebtoken.impl.ImmutableJwtParser.parseClaimsJws(ImmutableJwtParser.java:173) ~[jjwt-impl-0.11.5.jar:0.11.5]
at com.reservationproject.security.JwtProvider.validateToken(JwtProvider.java:55) ~[classes/:na]
at com.reservationproject.security.JwtAuthenticationFilter.doFilterInternal(JwtAuthenticationFilter.java:29) ~[classes/:na]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117) ~[spring-web-5.3.23.jar:5.3.23]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:346) ~[spring-security-web-5.7.4.jar:5.7.4]
at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:103) ~[spring-security-web-5.7.4.jar:5.7.4]
at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:89) ~[spring-security-web-5.7.4.jar:5.7.4]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:346) ~[spring-security-web-5.7.4.jar:5.7.4]
at org.springframework.security.web.header.HeaderWriterFilter.doHeadersAfter(HeaderWriterFilter.java:90) ~[spring-security-web-5.7.4.jar:5.7.4]
at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:75) ~[spring-security-web-5.7.4.jar:5.7.4]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117) ~[spring-web-5.3.23.jar:5.3.23]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:346) ~[spring-security-web-5.7.4.jar:5.7.4]
at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:112) ~[spring-security-web-5.7.4.jar:5.7.4]
at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:82) ~[spring-security-web-5.7.4.jar:5.7.4]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:346) ~[spring-security-web-5.7.4.jar:5.7.4]
at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:55) ~[spring-security-web-5.7.4.jar:5.7.4]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117) ~[spring-web-5.3.23.jar:5.3.23]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:346) ~[spring-security-web-5.7.4.jar:5.7.4]
at org.springframework.security.web.session.DisableEncodeUrlFilter.doFilterInternal(DisableEncodeUrlFilter.java:42) ~[spring-security-web-5.7.4.jar:5.7.4]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117) ~[spring-web-5.3.23.jar:5.3.23]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:346) ~[spring-security-web-5.7.4.jar:5.7.4]
at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:221) ~[spring-security-web-5.7.4.jar:5.7.4]
at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:186) ~[spring-security-web-5.7.4.jar:5.7.4]
at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:354) ~[spring-web-5.3.23.jar:5.3.23]
at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:267) ~[spring-web-5.3.23.jar:5.3.23]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[tomcat-embed-core-9.0.68.jar:9.0.68]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.68.jar:9.0.68]
at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100) ~[spring-web-5.3.23.jar:5.3.23]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117) ~[spring-web-5.3.23.jar:5.3.23]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[tomcat-embed-core-9.0.68.jar:9.0.68]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.68.jar:9.0.68]
at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93) ~[spring-web-5.3.23.jar:5.3.23]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117) ~[spring-web-5.3.23.jar:5.3.23]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[tomcat-embed-core-9.0.68.jar:9.0.68]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.68.jar:9.0.68]
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201) ~[spring-web-5.3.23.jar:5.3.23]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117) ~[spring-web-5.3.23.jar:5.3.23]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[tomcat-embed-core-9.0.68.jar:9.0.68]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.68.jar:9.0.68]
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:197) ~[tomcat-embed-core-9.0.68.jar:9.0.68]
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97) ~[tomcat-embed-core-9.0.68.jar:9.0.68]
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:541) ~[tomcat-embed-core-9.0.68.jar:9.0.68]
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:135) ~[tomcat-embed-core-9.0.68.jar:9.0.68]
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92) ~[tomcat-embed-core-9.0.68.jar:9.0.68]
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78) ~[tomcat-embed-core-9.0.68.jar:9.0.68]
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:360) ~[tomcat-embed-core-9.0.68.jar:9.0.68]
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:399) ~[tomcat-embed-core-9.0.68.jar:9.0.68]
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65) ~[tomcat-embed-core-9.0.68.jar:9.0.68]
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:893) ~[tomcat-embed-core-9.0.68.jar:9.0.68]
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1789) ~[tomcat-embed-core-9.0.68.jar:9.0.68]
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) ~[tomcat-embed-core-9.0.68.jar:9.0.68]
at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191) ~[tomcat-embed-core-9.0.68.jar:9.0.68]
at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659) ~[tomcat-embed-core-9.0.68.jar:9.0.68]
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) ~[tomcat-embed-core-9.0.68.jar:9.0.68]
at java.base/java.lang.Thread.run(Thread.java:833) ~[na:na]
我的SecurityConfig是:
@EnableWebSecurity
@Configuration
@RequiredArgsConstructor
public class SecurityConfig extends WebSecurityConfigurerAdapter {
private final UserDetailsService userDetailsService;
private final JwtAuthenticationFilter jwtAuthenticationFilter;
@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.authorizeRequests()
.antMatchers("/api/auth/**")
.permitAll()
.antMatchers(HttpMethod.GET, "/api/reservation/")
.permitAll()
.anyRequest()
.authenticated();
http.addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);
}
@Override
public void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService)
.passwordEncoder(passwordEncoder());
}
@Bean
PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
JwtProvider:
@Service
@RequiredArgsConstructor
public class JwtProvider {
private KeyStore keyStore;
@PostConstruct
public void init() {
try {
keyStore = KeyStore.getInstance("JKS");
InputStream resourceAsStream = getClass().getResourceAsStream("/springreservation.jks");
keyStore.load(resourceAsStream, "secret".toCharArray());
}
catch (KeyStoreException | CertificateException | NoSuchAlgorithmException | IOException e) {
throw new SpringReservationAccountException("Exception occured while loading keystore");
}
}
public String generateToken(Authentication authentication) {
User principal = (User) authentication.getPrincipal();
return Jwts.builder()
.setSubject(principal.getUsername())
.signWith(getPrivateKey())
.compact();
}
private PrivateKey getPrivateKey() {
try {
return (PrivateKey) keyStore.getKey("springreservation", "secret".toCharArray());
} catch (UnrecoverableKeyException | KeyStoreException | NoSuchAlgorithmException e) {
throw new SpringReservationAccountException("Exception occured while retrieving public key from keystore");
}
}
public boolean validateToken(String jwt) {
parserBuilder().setSigningKey(getPublicKey()).build().parseClaimsJws(jwt);
return true;
}
private PublicKey getPublicKey() {
try {
return keyStore.getCertificate("springreservation").getPublicKey();
} catch (KeyStoreException e) {
throw new SpringReservationAccountException("Probleem bij het ophalen van de publieke sleutel in de keystore");
}
}
public String getUsernameFromJwt(String token) {
Claims claims = parserBuilder().setSigningKey(getPublicKey()).build().parseClaimsJws(token).getBody();
return claims.getSubject();
}
}
ReservationController:
@RestController
@RequestMapping("/api/reservation")
@AllArgsConstructor
@Slf4j
public class ReservationController {
private ReservationService reservationService;
@PostMapping
public ResponseEntity<ReservationDto> createReservation(@RequestBody ReservationDto reservationDto) {
return ResponseEntity.status(HttpStatus.CREATED).body(reservationService.save(reservationDto));
}
@GetMapping
public ResponseEntity<List<ReservationDto>> getAllReservations() {
return ResponseEntity.status(HttpStatus.OK).body(reservationService.getAll());
}
}
预订域类:
@Getter
@Setter
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
@Entity(name = "reservations")
public class Reservation {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private Date date;
private Boolean voormiddag;
private Boolean namiddag;
@ManyToOne(fetch = FetchType.LAZY)
private Room room;
@OneToMany(fetch = FetchType.LAZY)
private List<User> user;
public Reservation(Date date, Boolean voormiddag, Boolean namiddag, Room room) {
this.date = date;
this.voormiddag = voormiddag;
this.namiddag = namiddag;
this.room = room;
}
public Boolean reachedMaxCapacity() {
return true;
}
}
JwtAuthenticationFilet:
@Component
public class JwtAuthenticationFilter extends OncePerRequestFilter {
@Autowired
private JwtProvider jwtProvider;
@Autowired
private UserDetailsService userDetailsService;
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
String jwt = getJwtFromRequest(request);
jwtProvider.validateToken(jwt);
if(StringUtils.hasText(jwt) && jwtProvider.validateToken(jwt)) {
String username = jwtProvider.getUsernameFromJwt(jwt);
UserDetails userDetails = userDetailsService.loadUserByUsername(username);
UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(null, userDetails.getAuthorities());
authenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
SecurityContextHolder.getContext();
}
filterChain.doFilter(request, response);
}
private String getJwtFromRequest(HttpServletRequest request) {
String bearerToken = request.getHeader("Authorization");
if (StringUtils.hasText(bearerToken) && bearerToken.startsWith("Bearer ")) {
return bearerToken.substring(7);
}
return bearerToken;
}
}
ReservationService:
@Service
@AllArgsConstructor
@Slf4j
public class ReservationService {
private final ReservationRepo reservationRepo;
@Transactional
public ReservationDto save(ReservationDto reservationDto) {
Reservation saveReservation = reservationRepo.save(mapReservationDto(reservationDto));
reservationDto.setId(saveReservation.getId());
return reservationDto;
}
@Transactional(readOnly = true)
public List<ReservationDto> getAll() {
return reservationRepo.findAll().stream().map(this::mapToDto).collect(toList());
}
private ReservationDto mapToDto(Reservation reservation) {
return ReservationDto.builder().date(reservation.getDate()).namiddag(reservation.getNamiddag()).voormiddag(reservation.getVoormiddag()).build();
}
private Reservation mapReservationDto(ReservationDto reservationDto) {
return Reservation.builder().date(reservationDto.getDate()).namiddag(reservationDto.getNamiddag()).voormiddag(reservationDto.getVoormiddag()).build();
}
}
如果需要更多的信息,请告诉我。
提前感谢!
发布于 2022-10-26 09:13:46
在您的过滤器中,您假定任何通过它的请求都会有一个“授权”头,但这是不正确的。
您的自定义筛选器应该将Authentication
设置为SecurityContextHolder
,但是在HttpSecurity
的.authorizeRequests()
方法中定义的规则在设置 Authentication
之后会检查。
因此,对任何请求都执行自定义筛选器,并且不受.permitAll()
或其他定义规则的影响--这就是为什么在不需要身份验证的端点上传递给JwtParser
而不是JWT字符串的null。
您可以通过重写OncePerRequestFilter
的OncePerRequestFilter
方法来定义not_filter逻辑来解决这个问题,例如:
private final List<RequestMatcher> excludedMatchers = List.of(
new AntPathRequestMatcher("/api/reservation/", HttpMethod.GET.name()),
new AntPathRequestMatcher("/api/auth/**"));
@Override
protected boolean shouldNotFilter(HttpServletRequest request) throws ServletException {
return excludedMatchers.stream()
.anyMatch(matcher -> matcher.matches(request));
}
https://stackoverflow.com/questions/74192895
复制相似问题