[toc]
1. 引入依赖
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>3.4.0</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.1</version>
</dependency>
2. 封装工具类
/**
* @Author 梦叶
*/
@Slf4j
public class JWTUtil {
/**
* 签名。不可泄漏
*/
private static final String SECRET = "51iros.com";
/**
* 颁发证书
* @param map 载体
* @param second 过期时间,秒
* @return
*/
public static String getToken(Map<String, String> map, int second) {
log.info("开始颁发证书 | playload:[{}] | second:[{}] ", JSON.toJSONString(map), second);
JWTCreator.Builder builder = JWT.create();
builder.withIssuedAt(new Date());//签发日期
//payload
map.forEach((k, v) -> {
builder.withClaim(k, v);
});
Calendar instance = Calendar.getInstance();
instance.add(Calendar.SECOND, second); //设置过期时间
builder.withExpiresAt(instance.getTime());//指定令牌的过期时间
String token = builder.sign(Algorithm.HMAC256(SECRET));//签名
return token;
}
/**
* 验证Token
* @param token
* @return
* @throws JWTVerificationException
*/
public static DecodedJWT verify (String token) throws JWTVerificationException {
//如果有任何验证异常,此处都会抛出异常
DecodedJWT decodedJWT = JWT.require(Algorithm.HMAC256(SECRET)).build().verify(token);
return decodedJWT;
}
/**
* 解析token
* @param token
* @return
* @throws JWTVerificationException
*/
public static SuperUser getUser(String token) throws JWTVerificationException {
SuperUser user = new SuperUser();
//如果有任何验证异常,此处都会抛出异常
DecodedJWT verify = verify(token);
user.setSuperUserId(verify.getClaim("superUserId").asInt());
user.setSuperUserName(verify.getClaim("superUserName").asString());
// user.setSuperUserName(verify.getClaim("superUserPassword").asString());
return user;
}
}
3. 拦截器配置
/**
* @Author 梦叶
*/
@Slf4j
public class LoginIntercept implements HandlerInterceptor {
/**
* 验证token
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
//获取请求头中的令牌
String token = request.getHeader("Authorization");
log.info("当前token为:{}", token);
CommResult<Object> result = new CommResult<>();
try {
//验证token
JWTUtil.verify(token);
return true;
} catch (SignatureVerificationException e) {
log.error("签名不一致",e.getMessage());
result.setCode(CommRespCode.BIZ_FAILED.getKey());
result.setMessage( "签名不一致");
} catch (TokenExpiredException e) {
log.error("令牌过期",e.getMessage());
result.setCode(CommRespCode.BIZ_FAILED.getKey());
result.setMessage( "令牌过期");
} catch (AlgorithmMismatchException e) {
log.error("算法不匹配",e.getMessage());
result.setCode(CommRespCode.BIZ_FAILED.getKey());
result.setMessage( "算法不匹配");
} catch (InvalidClaimException e) {
log.error("无效载体",e.getMessage());
result.setCode(CommRespCode.BIZ_FAILED.getKey());
result.setMessage( "无效载体");
} catch (Exception e) {
log.error("token无效",e.getMessage());
result.setCode(CommRespCode.BIZ_FAILED.getKey());
result.setMessage( "token无效");
}
String json = JSON.toJSONString(result);
//响应到前台: 将map转为json
response.setContentType("application/json;charset=UTF-8");
response.getWriter().println(json);
return false;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
log.info("验证通过");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
log.warn("url:[{}],准备进行登录验证",request.getRequestURI());
}
}
4. 将拦截器注册到IOC容器,并配置拦截与放行URL
/**
* @Author 梦叶
*/
@Configuration
public class InterceptorConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new LoginIntercept())
.excludePathPatterns("/register")//开通超管账号时放行
.excludePathPatterns("/supmgr/login")
.excludePathPatterns("/login")
.excludePathPatterns("/swagger-resources/**")
.excludePathPatterns("/doc.html")
.addPathPatterns("/**");
// .addPathPatterns("/supmgr/admin/**")
// .addPathPatterns("/admin/**");
}
}
5. 登录认证功能实现
/**
* <p>
* saas超级管理员用户表 服务实现类
* </p>
*
* @author 梦叶
* @since 2021-07-17
*/
@Service
public class SuperUserServiceImpl extends ServiceImpl<SuperUserMapper, SuperUser> implements SuperUserService {
//一小时
public static final int SECOND = 60 * 60 * 1;
/**
* 超管后台登录接口
*
* @param superUser
* @return
*/
@Override
public CommResult login(SuperUser superUser) {
if (BeanUtil.isEmpty(superUser)) {
return CommResult.error(CommRespCode.ILLEGAL_PARAM.getKey(), "请输入用户名密码");
}
if (StrUtil.isBlank(superUser.getSuperUserName())) {
return CommResult.error(CommRespCode.ILLEGAL_PARAM.getKey(), "用户名不能为空");
}
if (StrUtil.isBlank(superUser.getSuperUserPassword())) {
return CommResult.error(CommRespCode.ILLEGAL_PARAM.getKey(), "密码不能为空");
}
String userName = superUser.getSuperUserName();
SuperUser user = new LambdaQueryChainWrapper<SuperUser>(this.baseMapper)
.eq(SuperUser::getSuperUserName, userName)
.eq(SuperUser::getIsEnabled, true)
.one();
if (BeanUtil.isEmpty(user)) {
return CommResult.error(CommRespCode.ILLEGAL_PARAM.getKey(), "用户不存在");
}
//校验密码
//获取salt加盐加密
String salt = user.getSalt();
String sha256Hex = DigestUtil.sha256Hex(superUser.getSuperUserPassword() + salt);
String password = user.getSuperUserPassword();
if (!sha256Hex.equals(password)) {
return CommResult.error(CommRespCode.ILLEGAL_PARAM.getKey(), "密码错误");
}
//校验通过,颁发token
HashMap<String, String> userInfo = new HashMap<>();
userInfo.put("superUserId", user.getSuperUserId().toString());
userInfo.put("superUserName", user.getSuperUserName());
// String token = JWTUtil.getToken(userInfo, SECOND);
String token = JWTUtil.getToken(userInfo, 60);
//封装数据返回
HashMap<String, String> map = new HashMap<>();
map.put(HttpHeaders.AUTHORIZATION, token);
return CommResult.success(map);
}
/**
* 开通超级管理员账号
*
* @param superUser
* @return
*/
@Override
public CommResult register(SuperUser superUser) {
CheckNullUtil.check(superUser, "superUserName", "superUserPassword");
String superUserName = superUser.getSuperUserName();
String password = superUser.getSuperUserPassword();
if (superUserName.length() > 8) {
return CommResult.error(CommRespCode.BIZ_FAILED.getKey(), "用户名长度不能超过8");
}
//判断用户名是否重复
Integer count = this.baseMapper.selectCount(new LambdaQueryWrapper<SuperUser>().eq(SuperUser::getSuperUserName, superUser.getSuperUserName()));
if (count > 0) {
return CommResult.error(CommRespCode.BIZ_FAILED.getKey(), "用户已存在");
}
superUser.setIsEnabled(true);
//生成盐
String salt = RandomUtil.randomString(64);
//加盐加密
superUser.setSuperUserPassword(DigestUtil.sha256Hex(password + salt));
superUser.setSalt(salt);
return this.baseMapper.insert(superUser) > 0 ? CommResult.success() : CommResult.error(CommRespCode.BIZ_FAILED.getKey(), "开通超管失败");
}
}