4.0.0
org.springframework.boot
spring-boot-starter-parent
3.2.2
com.Alatus
NetCRM-server
0.0.1-SNAPSHOT
NetCRM-server
NetCRM-server
17
org.springframework.boot
spring-boot-starter-data-redis
org.springframework.boot
spring-boot-starter-security
org.springframework.boot
spring-boot-starter-web
org.mybatis.spring.boot
mybatis-spring-boot-starter
3.0.3
com.auth0
java-jwt
4.4.0
org.springframework.boot
spring-boot-devtools
runtime
true
com.mysql
mysql-connector-j
runtime
org.springframework.boot
spring-boot-configuration-processor
true
org.projectlombok
lombok
true
org.springframework.boot
spring-boot-starter-test
test
org.mybatis.spring.boot
mybatis-spring-boot-starter-test
3.0.3
test
org.springframework.security
spring-security-test
test
org.springframework.boot
spring-boot-maven-plugin
org.projectlombok
lombok
4.0.0
org.springframework.boot
spring-boot-starter-parent
3.2.2
com.Alatus
NetCRM-server
0.0.1-SNAPSHOT
NetCRM-server
NetCRM-server
17
org.springframework.boot
spring-boot-starter-data-redis
org.springframework.boot
spring-boot-starter-security
org.springframework.boot
spring-boot-starter-web
org.mybatis.spring.boot
mybatis-spring-boot-starter
3.0.3
com.auth0
java-jwt
4.4.0
org.springframework.boot
spring-boot-devtools
runtime
true
com.mysql
mysql-connector-j
runtime
org.springframework.boot
spring-boot-configuration-processor
true
org.projectlombok
lombok
true
org.springframework.boot
spring-boot-starter-test
test
org.mybatis.spring.boot
mybatis-spring-boot-starter-test
3.0.3
test
org.springframework.security
spring-security-test
test
org.springframework.boot
spring-boot-maven-plugin
org.projectlombok
lombok
package com.alatus.service;
import java.util.concurrent.TimeUnit;
public interface RedisService {
void setValue(String key,Object value);
Object getValue(String key);
Boolean removeValue(String key);
Boolean expire(String key, Long timeOut, TimeUnit timeUnit);
}
package com.alatus.service;
import java.util.concurrent.TimeUnit;
public interface RedisService {
void setValue(String key,Object value);
Object getValue(String key);
Boolean removeValue(String key);
Boolean expire(String key, Long timeOut, TimeUnit timeUnit);
}
package com.alatus.service.impl;
import com.alatus.service.RedisService;
import jakarta.annotation.Resource;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import java.util.concurrent.TimeUnit;
@Component
public class RedisServiceImpl implements RedisService {
// 数据源
@Resource
private RedisTemplate redisTemplate;
// 放入数据
@Override
public void setValue(String key, Object value) {
redisTemplate.opsForValue().set(key,value);
}
//取出数据
@Override
public Object getValue(String key) {
return redisTemplate.opsForValue().get(key);
}
//删除数据
@Override
public Boolean removeValue(String key) {
return redisTemplate.delete(key);
}
@Override
public Boolean expire(String key, Long timeOut, TimeUnit timeUnit) {
return redisTemplate.expire(key,timeOut,timeUnit);
}
}
package com.alatus.service.impl;
import com.alatus.service.RedisService;
import jakarta.annotation.Resource;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import java.util.concurrent.TimeUnit;
@Component
public class RedisServiceImpl implements RedisService {
// 数据源
@Resource
private RedisTemplate redisTemplate;
// 放入数据
@Override
public void setValue(String key, Object value) {
redisTemplate.opsForValue().set(key,value);
}
//取出数据
@Override
public Object getValue(String key) {
return redisTemplate.opsForValue().get(key);
}
//删除数据
@Override
public Boolean removeValue(String key) {
return redisTemplate.delete(key);
}
@Override
public Boolean expire(String key, Long timeOut, TimeUnit timeUnit) {
return redisTemplate.expire(key,timeOut,timeUnit);
}
}
package com.alatus.constant;
public class Constants {
public static final String LOGIN_URL = "/api/login";
// redis的key命名规范,项目名:模块名:功能名:唯一业务参数(比如用户ID)
public static final String REDIS_JWT_KEY = "crmSystem:user:login:";
// 七天时间
public static final Long EXPIRE_TIME = 7 * 24 * 60 * 60L;
// 三十分钟
public static final Long DEFAULT_EXPIRE_TIME = 30 * 60L;
}
package com.alatus.constant;
public class Constants {
public static final String LOGIN_URL = "/api/login";
// redis的key命名规范,项目名:模块名:功能名:唯一业务参数(比如用户ID)
public static final String REDIS_JWT_KEY = "crmSystem:user:login:";
// 七天时间
public static final Long EXPIRE_TIME = 7 * 24 * 60 * 60L;
// 三十分钟
public static final Long DEFAULT_EXPIRE_TIME = 30 * 60L;
}
package com.alatus.util;
import com.alatus.model.TUser;
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.TokenExpiredException;
import com.auth0.jwt.interfaces.Claim;
import com.auth0.jwt.interfaces.DecodedJWT;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* jwt的工具类
*
*/
public class JWTUtils {
private static final String SECRET = "dYB300olWQ3345;ld<3w48";
/**
* 生成jwt
*
* @return
*/
public static String createJWT(String userJSON) {
//组装头数据
Map header = new HashMap<>();
header.put("alg", "HS256");
header.put("typ", "JWT");
//链式编程
return JWT.create()
//头部
.withHeader(header)
//负载(可以有多个)
.withClaim("user", userJSON)
//签名
.sign(Algorithm.HMAC256(SECRET));
}
/**
* 验证jwt
*
*/
public static Boolean verifyJWT(String jwt) {
try {
// 使用密钥创建一个jwt验证器
JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256(SECRET)).build();
//jwt验证器验证jwt
jwtVerifier.verify(jwt); //如果此行代码没有抛出异常,就说明jwt验证通过,抛出异常,就说明jwt验证不通过
return true;
} catch (Exception e) {
e.printStackTrace();
}
return false;
}
/**
* 解析jwt
*
*/
public static String parseJWT(String jwt) {
Map map = new HashMap<>();
try {
// 使用密钥创建一个jwt验证器对象
JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256(SECRET)).build();
//jwt验证器对象验证jwt,得到一个解码后的jwt对象
DecodedJWT decodedJWT = jwtVerifier.verify(jwt);
//验证通过了,就开始解析负载里面的数据
Claim userJSON = decodedJWT.getClaim("user");
return userJSON.asString();
} catch (TokenExpiredException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
/**
* 解析jwt得到userId
*
* @param jwt
* @return
*/
public static Integer parseJWTByUserId(String jwt) {
String userJSON = parseJWT(jwt);
TUser user = JSONUtils.toBean(userJSON, TUser.class);
return user.getId();
}
/**
* 解析jwt得到userRole
*
* @param jwt
* @return
*/
public static List parseJWTByUserRole(String jwt) {
String userJSON = parseJWT(jwt);
TUser user = JSONUtils.toBean(userJSON, TUser.class);
return null;
}
}
package com.alatus.util;
import com.alatus.model.TUser;
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.TokenExpiredException;
import com.auth0.jwt.interfaces.Claim;
import com.auth0.jwt.interfaces.DecodedJWT;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* jwt的工具类
*
*/
public class JWTUtils {
private static final String SECRET = "dYB300olWQ3345;ld<3w48";
/**
* 生成jwt
*
* @return
*/
public static String createJWT(String userJSON) {
//组装头数据
Map header = new HashMap<>();
header.put("alg", "HS256");
header.put("typ", "JWT");
//链式编程
return JWT.create()
//头部
.withHeader(header)
//负载(可以有多个)
.withClaim("user", userJSON)
//签名
.sign(Algorithm.HMAC256(SECRET));
}
/**
* 验证jwt
*
*/
public static Boolean verifyJWT(String jwt) {
try {
// 使用密钥创建一个jwt验证器
JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256(SECRET)).build();
//jwt验证器验证jwt
jwtVerifier.verify(jwt); //如果此行代码没有抛出异常,就说明jwt验证通过,抛出异常,就说明jwt验证不通过
return true;
} catch (Exception e) {
e.printStackTrace();
}
return false;
}
/**
* 解析jwt
*
*/
public static String parseJWT(String jwt) {
Map map = new HashMap<>();
try {
// 使用密钥创建一个jwt验证器对象
JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256(SECRET)).build();
//jwt验证器对象验证jwt,得到一个解码后的jwt对象
DecodedJWT decodedJWT = jwtVerifier.verify(jwt);
//验证通过了,就开始解析负载里面的数据
Claim userJSON = decodedJWT.getClaim("user");
return userJSON.asString();
} catch (TokenExpiredException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
/**
* 解析jwt得到userId
*
* @param jwt
* @return
*/
public static Integer parseJWTByUserId(String jwt) {
String userJSON = parseJWT(jwt);
TUser user = JSONUtils.toBean(userJSON, TUser.class);
return user.getId();
}
/**
* 解析jwt得到userRole
*
* @param jwt
* @return
*/
public static List parseJWTByUserRole(String jwt) {
String userJSON = parseJWT(jwt);
TUser user = JSONUtils.toBean(userJSON, TUser.class);
return null;
}
}
package com.alatus.config.handler;
import com.alatus.constant.Constants;
import com.alatus.model.TUser;
import com.alatus.result.R;
import com.alatus.service.RedisService;
import com.alatus.util.JSONUtils;
import com.alatus.util.JWTUtils;
import com.alatus.util.ResponseUtils;
import jakarta.annotation.Resource;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.stereotype.Component;
import java.io.IOException;
import java.util.concurrent.TimeUnit;
@Component
public class MyAuthenticationSuccessHandler implements AuthenticationSuccessHandler {
@Resource
private RedisService redisService;
@Override
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
//由于禁用了session,我们在登录成功后,需要在服务器保持用户的登录状态,前端下次来访问服务器端的时候,服务器端要知道这个人登录了
TUser tUser = (TUser) authentication.getPrincipal();
// 登录成功的统一结果
R result = R.OK(tUser);
// 把R对象转为JSON
String resultJSON = JSONUtils.toJSON(result);
// 生成jwt
String jwt = JWTUtils.createJWT(resultJSON);
String key = Constants.REDIS_JWT_KEY+tUser.getId();
// 写入Redis
redisService.setValue(key,jwt);
// 设置jwt的过期时间,如果选择了记住我,jwt过期时间为七天,否则是30分钟
Boolean rememberMe = Boolean.valueOf(request.getParameter("rememberMe"));
if(rememberMe){
redisService.expire(key,Constants.EXPIRE_TIME, TimeUnit.SECONDS);
}
else{
redisService.expire(key,Constants.DEFAULT_EXPIRE_TIME,TimeUnit.SECONDS);
}
// 把R以JSON传回前端
ResponseUtils.write(response,jwt);
}
}
package com.alatus.config.handler;
import com.alatus.constant.Constants;
import com.alatus.model.TUser;
import com.alatus.result.R;
import com.alatus.service.RedisService;
import com.alatus.util.JSONUtils;
import com.alatus.util.JWTUtils;
import com.alatus.util.ResponseUtils;
import jakarta.annotation.Resource;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.stereotype.Component;
import java.io.IOException;
import java.util.concurrent.TimeUnit;
@Component
public class MyAuthenticationSuccessHandler implements AuthenticationSuccessHandler {
@Resource
private RedisService redisService;
@Override
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
//由于禁用了session,我们在登录成功后,需要在服务器保持用户的登录状态,前端下次来访问服务器端的时候,服务器端要知道这个人登录了
TUser tUser = (TUser) authentication.getPrincipal();
// 登录成功的统一结果
R result = R.OK(tUser);
// 把R对象转为JSON
String resultJSON = JSONUtils.toJSON(result);
// 生成jwt
String jwt = JWTUtils.createJWT(resultJSON);
String key = Constants.REDIS_JWT_KEY+tUser.getId();
// 写入Redis
redisService.setValue(key,jwt);
// 设置jwt的过期时间,如果选择了记住我,jwt过期时间为七天,否则是30分钟
Boolean rememberMe = Boolean.valueOf(request.getParameter("rememberMe"));
if(rememberMe){
redisService.expire(key,Constants.EXPIRE_TIME, TimeUnit.SECONDS);
}
else{
redisService.expire(key,Constants.DEFAULT_EXPIRE_TIME,TimeUnit.SECONDS);
}
// 把R以JSON传回前端
ResponseUtils.write(response,jwt);
}
}