jwt-token的发行

This commit is contained in:
none 2023-02-16 15:00:22 +08:00
parent 0e51cd7ceb
commit 53b3a8645f
11 changed files with 173 additions and 14 deletions

View File

@ -20,20 +20,18 @@ public class KaptchaConfig {
properties.setProperty(KAPTCHA_BORDER, "yes"); properties.setProperty(KAPTCHA_BORDER, "yes");
// 字符颜色 // 字符颜色
properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_COLOR, "black"); properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_COLOR, "black");
// 字符间距
properties.setProperty(KAPTCHA_TEXTPRODUCER_CHAR_SPACE, "5");
// 图片宽度 // 图片宽度
properties.setProperty(KAPTCHA_IMAGE_WIDTH, "120"); properties.setProperty(KAPTCHA_IMAGE_WIDTH, "120");
// 图片高度 // 图片高度
properties.setProperty(KAPTCHA_IMAGE_HEIGHT, "40"); properties.setProperty(KAPTCHA_IMAGE_HEIGHT, "50");
// 字符大小 // 字符大小
properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_SIZE, "38"); properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_SIZE, "40");
// 验证键码
properties.setProperty(KAPTCHA_SESSION_CONFIG_KEY, "playedu");
// 字符长度 // 字符长度
properties.setProperty(KAPTCHA_TEXTPRODUCER_CHAR_LENGTH, "4"); properties.setProperty(KAPTCHA_TEXTPRODUCER_CHAR_LENGTH, "4");
// 字体样式 // 字体样式
properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_NAMES, "Arial,Courier"); properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_NAMES, "Arial,Courier");
// 图片样式
properties.setProperty(KAPTCHA_OBSCURIFICATOR_IMPL, "com.google.code.kaptcha.impl.ShadowGimpy");
defaultKaptcha.setConfig(new Config(properties)); defaultKaptcha.setConfig(new Config(properties));

View File

@ -0,0 +1,7 @@
package xyz.playedu.api.constant;
public class SystemConstant {
public final static String JWT_PRV_ADMIN_USER = "dc14511e97e7eb725fb2976bc939b375";
}

View File

@ -1,18 +1,26 @@
package xyz.playedu.api.controller.admin; package xyz.playedu.api.controller.admin;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import xyz.playedu.api.constant.SystemConstant;
import xyz.playedu.api.domain.AdminUser; import xyz.playedu.api.domain.AdminUser;
import xyz.playedu.api.middleware.ImageCaptchaCheckMiddleware; import xyz.playedu.api.middleware.ImageCaptchaCheckMiddleware;
import xyz.playedu.api.request.LoginRequest; import xyz.playedu.api.request.LoginRequest;
import xyz.playedu.api.service.AdminUserService; import xyz.playedu.api.service.AdminUserService;
import xyz.playedu.api.service.JWTService;
import xyz.playedu.api.types.JsonResponse; import xyz.playedu.api.types.JsonResponse;
import xyz.playedu.api.types.JwtToken;
import xyz.playedu.api.util.MD5Util; import xyz.playedu.api.util.MD5Util;
import xyz.playedu.api.util.RequestUtil;
import java.util.HashMap;
@Slf4j
@RestController @RestController
@RequestMapping("/admin/v1/auth") @RequestMapping("/admin/v1/auth")
public class LoginController { public class LoginController {
@ -20,6 +28,9 @@ public class LoginController {
@Autowired @Autowired
private AdminUserService adminUserService; private AdminUserService adminUserService;
@Autowired
private JWTService jwtService;
@PostMapping("/login") @PostMapping("/login")
@ImageCaptchaCheckMiddleware @ImageCaptchaCheckMiddleware
public JsonResponse login(@RequestBody @Validated LoginRequest loginRequest) { public JsonResponse login(@RequestBody @Validated LoginRequest loginRequest) {
@ -27,14 +38,22 @@ public class LoginController {
if (adminUser == null) { if (adminUser == null) {
return JsonResponse.error("邮箱不存在"); return JsonResponse.error("邮箱不存在");
} }
String password = MD5Util.md5(loginRequest.getPassword() + adminUser.getSalt()); String password = MD5Util.md5(loginRequest.getPassword() + adminUser.getSalt()).toLowerCase();
if (password != adminUser.getPassword()) { if (!adminUser.getPassword().equals(password)) {
return JsonResponse.error("密码错误"); return JsonResponse.error("密码错误");
} }
if (adminUser.getIsBanLogin() == 1) { if (adminUser.getIsBanLogin() == 1) {
return JsonResponse.error("当前用户禁止登录"); return JsonResponse.error("当前用户禁止登录");
} }
return JsonResponse.success("success");
String url = RequestUtil.url();
JwtToken token = jwtService.generate(adminUser.getId(), url, SystemConstant.JWT_PRV_ADMIN_USER);
HashMap<String, Object> data = new HashMap<>();
data.put("token", token.getToken());
data.put("expire", token.getExpire());
return JsonResponse.data(data);
} }
@PostMapping("/logout") @PostMapping("/logout")

View File

@ -8,7 +8,7 @@ import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import xyz.playedu.api.service.ImageCaptchaService; import xyz.playedu.api.service.ImageCaptchaService;
import xyz.playedu.api.types.ImageCaptchaRequestInterface; import xyz.playedu.api.request.types.ImageCaptchaRequestInterface;
import xyz.playedu.api.types.JsonResponse; import xyz.playedu.api.types.JsonResponse;
@Aspect @Aspect

View File

@ -2,7 +2,7 @@ package xyz.playedu.api.request;
import jakarta.validation.constraints.NotNull; import jakarta.validation.constraints.NotNull;
import lombok.Data; import lombok.Data;
import xyz.playedu.api.types.ImageCaptchaRequestInterface; import xyz.playedu.api.request.types.ImageCaptchaRequestInterface;
import java.io.Serializable; import java.io.Serializable;

View File

@ -1,4 +1,4 @@
package xyz.playedu.api.types; package xyz.playedu.api.request.types;
public interface ImageCaptchaRequestInterface { public interface ImageCaptchaRequestInterface {

View File

@ -0,0 +1,7 @@
package xyz.playedu.api.service;
import xyz.playedu.api.types.JwtToken;
public interface JWTService {
JwtToken generate(Integer userId, String iss, String prv);
}

View File

@ -0,0 +1,59 @@
package xyz.playedu.api.service.impl;
import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.security.Keys;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import xyz.playedu.api.service.JWTService;
import xyz.playedu.api.types.JWTPayload;
import xyz.playedu.api.types.JwtToken;
import xyz.playedu.api.util.ToolUtil;
import javax.crypto.SecretKey;
import java.nio.charset.StandardCharsets;
import java.util.Date;
@Slf4j
@Service
public class JwtServiceImpl implements JWTService {
@Value("${playedu.jwt.key}")
private String ConfigKey;
@Value("${playedu.jwt.expire}")
private Long ConfigExpire;
public JwtToken generate(Integer userId, String iss, String prv) {
long curTime = System.currentTimeMillis();
JWTPayload payload = new JWTPayload();
payload.setPrv(prv);
payload.setIss(iss);
payload.setJti(ToolUtil.uuid());
payload.setNbf(curTime);
payload.setIat(curTime);
payload.setExp(curTime + ConfigExpire);
payload.setSub(userId);
SecretKey key = Keys.hmacShaKeyFor(ConfigKey.getBytes(StandardCharsets.UTF_8));
JwtBuilder builder = Jwts.builder();
builder.setId(payload.getJti()).setIssuedAt(new Date(payload.getIat())).claim("prv", payload.getPrv());
builder.setExpiration(new Date(payload.getExp())).setIssuer(payload.getIss());
builder.setSubject(String.valueOf(payload.getSub())).setNotBefore(new Date(payload.getNbf()));
builder.signWith(key);
JwtToken token = new JwtToken();
token.setToken(builder.compact());
token.setExpire(payload.getExp() / 1000);
return token;
}
public JWTPayload parse(String token) {
return null;
}
}

View File

@ -0,0 +1,50 @@
package xyz.playedu.api.types;
import lombok.Data;
import java.util.HashMap;
/**
* @see https://www.rfc-editor.org/rfc/rfc7519#section-4.1
*/
@Data
public class JWTPayload {
/**
* subject
*/
private Integer sub;
/**
* Issued At
*/
private Long iat;
/**
* Expiration Time
*/
private Long exp;
/**
* Not Before
*/
private Long nbf;
/**
* JWT ID
*/
private String jti;
/**
* Issuer
*/
private String iss;
/**
* Payload
*/
private String prv;
private HashMap<String, Object> claims;
}

View File

@ -0,0 +1,12 @@
package xyz.playedu.api.types;
import lombok.Data;
@Data
public class JwtToken {
private String token;
private Long expire;
}

View File

@ -31,8 +31,15 @@ mybatis-plus:
configuration: configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
# PlayEdu
playedu: playedu:
# 图形验证码
captcha: captcha:
expire: 300 #分5钟 expire: 300 #有效期[单位:秒,默认5分钟]
cache-prefix: "captcha:key:" cache-prefix: "captcha:key:" #存储key的前缀
# JWT
jwt:
key: "eJTJSLPv13fw9twbuPoeicypLqnSfYWL" #32个字符,加密key用来加密jwt的数据[运行本系统之前请务必修改]
expire: 1296000 #token有效期[单位:秒,默认15天]