feat: 添加JWT登录功能 - AuthController、JwtUtil、登录拦截器
This commit is contained in:
parent
6e9535bd89
commit
69ef12aa2b
8 changed files with 207 additions and 0 deletions
37
src/main/java/edu/situ/stlserver/config/AuthInterceptor.java
Normal file
37
src/main/java/edu/situ/stlserver/config/AuthInterceptor.java
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
16
src/main/java/edu/situ/stlserver/config/WebConfig.java
Normal file
16
src/main/java/edu/situ/stlserver/config/WebConfig.java
Normal 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");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
12
src/main/java/edu/situ/stlserver/dao/UserMapper.java
Normal file
12
src/main/java/edu/situ/stlserver/dao/UserMapper.java
Normal 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);
|
||||||
|
}
|
||||||
11
src/main/java/edu/situ/stlserver/model/dto/LoginDTO.java
Normal file
11
src/main/java/edu/situ/stlserver/model/dto/LoginDTO.java
Normal 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;
|
||||||
|
}
|
||||||
15
src/main/java/edu/situ/stlserver/model/entity/User.java
Normal file
15
src/main/java/edu/situ/stlserver/model/entity/User.java
Normal 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;
|
||||||
|
}
|
||||||
51
src/main/java/edu/situ/stlserver/util/JwtUtil.java
Normal file
51
src/main/java/edu/situ/stlserver/util/JwtUtil.java
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
11
src/main/resources/schema-user.sql
Normal file
11
src/main/resources/schema-user.sql
Normal 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', '管理员');
|
||||||
Loading…
Add table
Add a link
Reference in a new issue