我已经为此工作了一段时间,我用来帮助我的视频是 2019 年的,所以它有点过时了,但我认为我可以解决这些问题。该程序运行但是当我尝试使用邮递员时我收到 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));
}
}
安全配置器
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