我研究这个已经有一段时间了,我用来帮助我的视频是从2019年开始的,所以有点过时了,但我认为我可以解决这些问题。程序运行,但当我尝试使用postman时,我得到一个401未经授权的错误:
下面是jwtutil.java文件代码:package com.stdbankjwtauth.authsystem.util;
import java.util.Map;
import java.util.function.Function;
import java.util.Date;
import java.util.HashMap;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Service;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
@Service
public class JwtUtil {
private String SECRET_KEY = "secret";
public String extractUsername(String token) {
return extractClaim(token, Claims::getSubject);
}
public Date extractExpiration(String token) {
return extractClaim(token,Claims::getExpiration);
}
public <T> T extractClaim(String token, Function<Claims,T> claimsResolver) {
final Claims claims = extractAllClaims(token);
return claimsResolver.apply(claims);
}
private Claims extractAllClaims(String token) {
return Jwts.parser().setSigningKey(SECRET_KEY).parseClaimsJws(token).getBody();
}
private boolean isTokenExpired(String token) {
return extractExpiration(token).before(new Date());
}
public String generateToken(UserDetails userDetails) {
Map<String,Object> claims = new HashMap<>();
return createToken(claims,userDetails.getUsername());
}
private String createToken(Map<String,Object> claims, String Subject) {
return Jwts.builder().setClaims(claims).setSubject(Subject).setIssuedAt(new Date(System.currentTimeMillis()))
.setExpiration(new Date(System.currentTimeMillis()+1000*60*60*10))
.signWith(SignatureAlgorithm.HS256,SECRET_KEY).compact();
}
public boolean validateToken(String token, UserDetails userDetails){
final String username = extractUsername(token);
return (username.equals(userDetails.getUsername()) && !isTokenExpired(token));
}
}
AuthenticationRequest.java
package com.stdbankjwtauth.authsystem.models;
public class AuthenticationRequest {
private String username;
private String password;
public AuthenticationRequest(String Username,String Password) {
this.username = Username;
this.password = Password;
}
public String getUsername() {
return username;
}
public void setUsername(String Username) {
this.username = Username;
}
public String getPassword() {
return password;
}
public void setPassword(String Password) {
this.password = Password;
}
}
AuthenticationResponse.java
package com.stdbankjwtauth.authsystem.models;
public class AuthenticationResponse {
private final String jwt;
public AuthenticationResponse(String Jwt) {
this.jwt = Jwt;
}
public String getJwt() {
return jwt;
}
}
AuthenticationEndpoint.java
package com.stdbankjwtauth.authsystem;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import com.stdbankjwtauth.authsystem.models.AuthenticationRequest;
import com.stdbankjwtauth.authsystem.models.AuthenticationResponse;
import com.stdbankjwtauth.authsystem.util.JwtUtil;
@RestController
public class AuthenticateEnpoint {
@Autowired
private AuthenticationManager authenticationManager;
@Autowired
private UserDetailsService userDetailsService;
@Autowired
private JwtUtil jwtTokenUtil;
@PostMapping("/authenticates")
public ResponseEntity <?> createAuthenticationToken(@RequestBody AuthenticationRequest authenticationRequest) throws Exception{
try {
authenticationManager.authenticate(
new UsernamePasswordAuthenticationToken(authenticationRequest.getUsername(),authenticationRequest.getPassword())
);
}catch(BadCredentialsException e) {
throw new Exception("Incorrect username or password",e);
}
final UserDetails userDetails = userDetailsService
.loadUserByUsername(authenticationRequest.getUsername());
final String jwt = jwtTokenUtil.generateToken(userDetails);
return ResponseEntity.ok(new AuthenticationResponse(jwt));
}
}
SecurityConfigurer
package com.stdbankjwtauth.authsystem;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
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.WebSecurityConfiguration;
import org.springframework.security.config.http.SessionCreationPolicy;
@Configuration
@EnableWebSecurity
public class SecurirtyConfigurer extends WebSecurityConfiguration {
protected void configure(AuthenticationManagerBuilder auth) throws Exception{
auth.getDefaultUserDetailsService();
}
@Bean
public AuthenticationManager authenticationManager(HttpSecurity http) throws Exception {
return http.getSharedObject(AuthenticationManagerBuilder.class)
.build();
}
protected void configure(HttpSecurity http) throws Exception{
http
.csrf()
.disable()
.authorizeHttpRequests().requestMatchers("/authenticates").permitAll()
.anyRequest().authenticated()
.and().sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS);
}
}
FileBasedAuthSystem.java
package com.stdbankjwtauth.authsystem.services;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.List;
import java.util.ArrayList;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.core.userdetails.User;
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.factory.PasswordEncoderFactories;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
import org.springframework.stereotype.Service;
@Configuration
@Service
public class FileBasedUserDetailsService {
private static final String FILE_PATH = "C:\repos\STDBank-JWT-Auth-System\stdbank-jwt-auth\credentials.txt";
@Bean
public InMemoryUserDetailsManager userDetailsService() {
List<String> lines = new ArrayList<>();
try {
lines = Files.readAllLines(Paths.get(FILE_PATH));
}catch (Exception e) {
e.printStackTrace();
}
for (String line : lines) {
String[] parts = line.split(":");
PasswordEncoder encoder = PasswordEncoderFactories.createDelegatingPasswordEncoder();
UserDetails user = User.withUsername(parts[0])
.password(encoder.encode(parts[1]))
.roles("USER")
.build();
return new InMemoryUserDetailsManager(user);
}
throw new UsernameNotFoundException("Username not found: "+ lines);
}
}
这是我使用的youtube视频链接https://www.youtube.com/watch?v=X80nJ5T7YpE&t=81s
这是我在Postman
中得到的错误类路径中可能缺少JAXB库(XML绑定的Java体系结构)。JABX直到java版本10才出现,然后从java SE从java 11或更新版本中删除,它被转移到java EE下的Jakarta EE项目。
要修复此错误,您可以使用以下选项
- 使用旧版本的jdk,默认使用JAXB库。
- 在项目的pom.xml文件中指定jaxb-api依赖项,如下所述:
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.3.0</version>
</dependency>
详情请访问:https://www.codejava.net/coding/solved-java-lang-noclassdeffounderror-javax-xml-bind-jaxbexception