pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.example</groupId>
<artifactId>test</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<artifactId>oauth_jwt</artifactId>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security.oauth.boot</groupId>
<artifactId>spring-security-oauth2-autoconfigure</artifactId>
<version>2.1.0.RELEASE</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-api</artifactId>
<version>0.11.2</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-impl</artifactId>
<version>0.11.2</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-jackson</artifactId>
<version>0.11.2</version>
<scope>runtime</scope>
</dependency>
</dependencies>
</project>
application.yaml
server:
port: 6661
security:
oauth2:
resource:
jwt:
key-value:
7ECF6B8297F141A0F25804087D0CF96F604A9A3542C5BA6631CED0A41E31F682
controller
import org.example.component.JwtUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
/**
* @author: jg
* @date: 2024-07-30
* @description:
*/
@RestController
public class UserController {
@Autowired
private JwtUtil jwtUtil;
@PostMapping("/login")
public String login(@RequestParam("username") String username, @RequestParam("password") String password) {
// 验证用户名和密码,这里只是示例,实际应用中需要查询数据库或其他方式验证用户身份
if ("user".equals(username) && "password".equals(password)) {
// 实际情况下,应该使用依赖注入的方式获取JwtUtil实例
String token = jwtUtil.generateToken(username);
return "Bearer " + token;
} else {
throw new RuntimeException("Invalid username or password");
}
}
@GetMapping("/protected")
public String getProtectedResource() {
return "This is a protected resource";
}
}
config
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;
import io.jsonwebtoken.Claims;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* @author: jg
* @date: 2024-07-30
* @description:
*/
@Component
public class JwtAuthenticationFilter extends OncePerRequestFilter {
private JwtUtil jwtUtil;
public JwtAuthenticationFilter(JwtUtil jwtUtil) {
this.jwtUtil = jwtUtil;
}
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
String token = request.getHeader("Authorization");
String requestURI = request.getRequestURI();
if (token != null && token.startsWith("Bearer ")) {
token = token.substring(7);
try {
Claims claims = jwtUtil.getClaimsFromToken(token);
String username = claims.getSubject();
if (username != null) {
UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(username, null, null);
authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
SecurityContextHolder.getContext().setAuthentication(authentication);
}
} catch (Exception e) {
// Invalid token, handle the exception as needed
System.out.println("Invalid token");
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
response.getWriter().write("{\"error\": \"Invalid or expired token\"}");
return;
}
}else if (!requestURI.equals("/login")){
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
response.setCharacterEncoding("UTF-8");
response.getWriter().write("{\"error\": \"请求头不存在 Authorization 属性或值不是Bearer 开头\"}");
return;
}
filterChain.doFilter(request, response);
}
}
util
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import java.util.Date;
/**
* @author: jg
* @date: 2024-07-30
* @description:
*/
@Component
public class JwtUtil {
@Value("${security.oauth2.resource.jwt.key-value}")
private String jwtSecret;
/* @Value("${security.oauth2.resource.jwt.algorithm}")
private String jwtAlgorithm;*/
public String generateToken(String username) {
return Jwts.builder()
.setSubject(username)
.setIssuedAt(new Date())
.signWith(SignatureAlgorithm.HS256, jwtSecret)
.compact();
}
public Claims getClaimsFromToken(String token) {
return Jwts.parser()
.setSigningKey(jwtSecret)
.parseClaimsJws(token)
.getBody();
}
}
filter
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;
import io.jsonwebtoken.Claims;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* @author: jg
* @date: 2024-07-30
* @description:
*/
@Component
public class JwtAuthenticationFilter extends OncePerRequestFilter {
private JwtUtil jwtUtil;
public JwtAuthenticationFilter(JwtUtil jwtUtil) {
this.jwtUtil = jwtUtil;
}
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
String token = request.getHeader("Authorization");
if (token != null && token.startsWith("Bearer ")) {
token = token.substring(7);
try {
Claims claims = jwtUtil.getClaimsFromToken(token);
String username = claims.getSubject();
if (username != null) {
UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(username, null, null);
authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
SecurityContextHolder.getContext().setAuthentication(authentication);
}
} catch (Exception e) {
// Invalid token, handle the exception as needed
System.out.println("Invalid token");
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
response.getWriter().write("{\"error\": \"Invalid or expired token\"}");
return;
}
}else {
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
response.setCharacterEncoding("UTF-8");
response.getWriter().write("{\"error\": \"请求头不存在 Authorization 属性或值不是Bearer 开头\"}");
return;
}
filterChain.doFilter(request, response);
}
}