feat: 添加JWT登录功能 - AuthController、JwtUtil、登录拦截器

This commit is contained in:
Administrator 2026-07-12 15:24:04 +08:00
commit 69ef12aa2b
8 changed files with 207 additions and 0 deletions

View file

@ -0,0 +1,37 @@
package edu.situ.stlserver.config;
import edu.situ.stlserver.util.JwtUtil;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.HandlerInterceptor;
public class AuthInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
// 放行登录接口
if (request.getRequestURI().contains("/auth/login")) {
return true;
}
// 放行静态资源和Swagger
if (request.getRequestURI().contains("/index.html")
|| request.getRequestURI().contains("/v3/api-docs")
|| request.getRequestURI().contains("/swagger-ui")) {
return true;
}
String authHeader = request.getHeader("Authorization");
if (authHeader == null || !authHeader.startsWith("Bearer ")) {
response.setStatus(401);
return false;
}
String token = authHeader.replace("Bearer ", "");
if (!JwtUtil.isTokenValid(token)) {
response.setStatus(401);
return false;
}
return true;
}
}

View file

@ -0,0 +1,16 @@
package edu.situ.stlserver.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new AuthInterceptor())
.addPathPatterns("/**")
.excludePathPatterns("/auth/login");
}
}

View file

@ -0,0 +1,54 @@
package edu.situ.stlserver.controller;
import edu.situ.stlserver.dao.UserMapper;
import edu.situ.stlserver.model.dto.LoginDTO;
import edu.situ.stlserver.model.entity.User;
import edu.situ.stlserver.model.vo.HttpResult;
import edu.situ.stlserver.util.JwtUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.HashMap;
import java.util.Map;
@RestController
@RequestMapping("/auth")
public class AuthController {
@Autowired
private UserMapper userMapper;
@PostMapping("/login")
public HttpResult login(@RequestBody LoginDTO loginDTO) {
User user = userMapper.selectByUsername(loginDTO.getUsername());
if (user == null) {
return HttpResult.error("用户名或密码错误");
}
if (!user.getPassword().equals(loginDTO.getPassword())) {
return HttpResult.error("用户名或密码错误");
}
String token = JwtUtil.generateToken(user.getId(), user.getUsername());
Map<String, Object> data = new HashMap<>();
data.put("token", token);
data.put("nickname", user.getNickname());
return HttpResult.success(data);
}
@GetMapping("/info")
public HttpResult info(@RequestHeader("Authorization") String authHeader) {
String token = authHeader.replace("Bearer ", "");
if (!JwtUtil.isTokenValid(token)) {
return HttpResult.unauthorized();
}
String username = JwtUtil.getUsername(token);
User user = userMapper.selectByUsername(username);
if (user == null) {
return HttpResult.error("用户不存在");
}
Map<String, Object> data = new HashMap<>();
data.put("id", user.getId());
data.put("username", user.getUsername());
data.put("nickname", user.getNickname());
return HttpResult.success(data);
}
}

View file

@ -0,0 +1,12 @@
package edu.situ.stlserver.dao;
import edu.situ.stlserver.model.entity.User;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;
@Mapper
public interface UserMapper {
@Select("SELECT * FROM users WHERE username = #{username}")
User selectByUsername(String username);
}

View file

@ -0,0 +1,11 @@
package edu.situ.stlserver.model.dto;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
public class LoginDTO {
private String username;
private String password;
}

View file

@ -0,0 +1,15 @@
package edu.situ.stlserver.model.entity;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;
@ToString
@NoArgsConstructor
@Data
public class User {
private Integer id;
private String username;
private String password;
private String nickname;
}

View file

@ -0,0 +1,51 @@
package edu.situ.stlserver.util;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.security.Keys;
import javax.crypto.SecretKey;
import java.util.Date;
public class JwtUtil {
private static final String SECRET = "stl-gym-secret-key-2024-very-long-string";
private static final long EXPIRE = 24 * 60 * 60 * 1000; // 24小时
private static SecretKey getKey() {
return Keys.hmacShaKeyFor(SECRET.getBytes());
}
public static String generateToken(Integer userId, String username) {
return Jwts.builder()
.subject(String.valueOf(userId))
.claim("username", username)
.issuedAt(new Date())
.expiration(new Date(System.currentTimeMillis() + EXPIRE))
.signWith(getKey())
.compact();
}
public static Claims parseToken(String token) {
return Jwts.parser()
.verifyWith(getKey())
.build()
.parseSignedClaims(token)
.getPayload();
}
public static Integer getUserId(String token) {
return Integer.parseInt(parseToken(token).getSubject());
}
public static String getUsername(String token) {
return parseToken(token).get("username", String.class);
}
public static boolean isTokenValid(String token) {
try {
return parseToken(token).getExpiration().after(new Date());
} catch (Exception e) {
return false;
}
}
}

View file

@ -0,0 +1,11 @@
-- 用户表(用于登录)
CREATE TABLE IF NOT EXISTS `users` (
`id` INT AUTO_INCREMENT PRIMARY KEY,
`username` VARCHAR(50) NOT NULL UNIQUE,
`password` VARCHAR(100) NOT NULL,
`nickname` VARCHAR(50) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-- 插入默认管理员账号
INSERT INTO `users` (`username`, `password`, `nickname`) VALUES
('admin', '123456', '管理员');