Initial commit
This commit is contained in:
@@ -0,0 +1,16 @@
|
||||
package com.linln.component.jwt.annotation;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* 忽略jwt权限验证注解(只在拦截的地址内有效)
|
||||
* @author gion
|
||||
* @date 2019/4/14
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.METHOD)
|
||||
public @interface IgnorePermissions {
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package com.linln.component.jwt.annotation;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* jwt权限注解(需要权限)
|
||||
* @author gion
|
||||
* @date 2019/4/13
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.METHOD)
|
||||
public @interface JwtPermissions {
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
package com.linln.component.jwt.annotation;
|
||||
|
||||
import com.auth0.jwt.exceptions.JWTVerificationException;
|
||||
import com.auth0.jwt.exceptions.TokenExpiredException;
|
||||
import com.linln.common.exception.ResultException;
|
||||
import com.linln.component.jwt.config.properties.JwtProjectProperties;
|
||||
import com.linln.component.jwt.enums.JwtResultEnums;
|
||||
import com.linln.component.jwt.utlis.JwtUtil;
|
||||
import org.aspectj.lang.ProceedingJoinPoint;
|
||||
import org.aspectj.lang.annotation.Around;
|
||||
import org.aspectj.lang.annotation.Aspect;
|
||||
import org.aspectj.lang.annotation.Pointcut;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
/**
|
||||
* Jwt权限注解AOP
|
||||
* @author gion
|
||||
* @date 2019/4/13
|
||||
*/
|
||||
@Aspect
|
||||
@Component
|
||||
@ConditionalOnProperty(name = "project.jwt.pattern-anno", havingValue = "true", matchIfMissing = true)
|
||||
public class JwtPermissionsAop {
|
||||
|
||||
@Autowired
|
||||
private JwtProjectProperties jwtProperties;
|
||||
|
||||
@Autowired
|
||||
private HttpServletRequest request;
|
||||
|
||||
@Pointcut("@annotation(com.linln.component.jwt.annotation.JwtPermissions)")
|
||||
public void jwtPermissions() {};
|
||||
|
||||
@Around("jwtPermissions()")
|
||||
public Object doPermission(ProceedingJoinPoint point) throws Throwable {
|
||||
|
||||
// 获取请求对象头部token数据
|
||||
String token = JwtUtil.getRequestToken(request);
|
||||
|
||||
// 验证token数据是否正确
|
||||
try {
|
||||
JwtUtil.verifyToken(token, jwtProperties.getSecret());
|
||||
} catch (TokenExpiredException e) {
|
||||
throw new ResultException(JwtResultEnums.TOKEN_EXPIRED);
|
||||
} catch (JWTVerificationException e) {
|
||||
throw new ResultException(JwtResultEnums.TOKEN_ERROR);
|
||||
}
|
||||
|
||||
return point.proceed();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package com.linln.component.jwt.config;
|
||||
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
|
||||
/**
|
||||
* @author gion
|
||||
* @date 2021/3/19
|
||||
*/
|
||||
@ComponentScan(basePackages = "com.linln.component.jwt")
|
||||
public class JwtAutoConfig {
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package com.linln.component.jwt.config;
|
||||
|
||||
import com.linln.component.jwt.interceptor.AuthenticationInterceptor;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||
|
||||
/**
|
||||
* jwt权限配置拦截器
|
||||
* @author gion
|
||||
* @date 2019/4/12
|
||||
*/
|
||||
@Configuration
|
||||
@ConditionalOnProperty(name = "project.jwt.pattern-path", havingValue = "true")
|
||||
public class JwtInterceptorConfig implements WebMvcConfigurer {
|
||||
|
||||
@Autowired
|
||||
private AuthenticationInterceptor authenticationInterceptor;
|
||||
|
||||
@Override
|
||||
public void addInterceptors(InterceptorRegistry registry) {
|
||||
registry.addInterceptor(authenticationInterceptor).addPathPatterns("/api/**");
|
||||
}
|
||||
}
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
package com.linln.component.jwt.config.properties;
|
||||
|
||||
import lombok.Data;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
/**
|
||||
* jwt配置项
|
||||
* @author gion
|
||||
* @date 2019/4/13
|
||||
*/
|
||||
@Data
|
||||
@Configuration
|
||||
@ConfigurationProperties(prefix = "project.jwt")
|
||||
public class JwtProjectProperties {
|
||||
|
||||
/** jwt秘钥 */
|
||||
private String secret = "mySecret";
|
||||
|
||||
/** 过期时间(天),默认3天 */
|
||||
private Integer expired = 3;
|
||||
|
||||
/** 权限模式-路径拦截 */
|
||||
private boolean patternPath = false;
|
||||
|
||||
/** 权限模式-注解拦截 */
|
||||
private boolean patternAnno = true;
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
package com.linln.component.jwt.controller;
|
||||
|
||||
import com.linln.common.enums.StatusEnum;
|
||||
import com.linln.common.exception.ResultException;
|
||||
import com.linln.common.utils.EncryptUtil;
|
||||
import com.linln.common.utils.ResultVoUtil;
|
||||
import com.linln.common.vo.ResultVo;
|
||||
import com.linln.component.jwt.annotation.IgnorePermissions;
|
||||
import com.linln.component.jwt.config.properties.JwtProjectProperties;
|
||||
import com.linln.component.jwt.enums.JwtResultEnums;
|
||||
import com.linln.component.jwt.utlis.JwtUtil;
|
||||
import com.linln.modules.system.domain.User;
|
||||
import com.linln.modules.system.service.UserService;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import io.swagger.annotations.ApiParam;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
/**
|
||||
* 默认登录验证控制器
|
||||
* 说明:默认采用系统用户进行登录验证
|
||||
*
|
||||
* @author gion
|
||||
* @date 2019/4/9
|
||||
*/
|
||||
@RestController
|
||||
@Api(tags = "登录接口")
|
||||
public class AuthController {
|
||||
|
||||
@Autowired
|
||||
private JwtProjectProperties properties;
|
||||
|
||||
@Autowired
|
||||
private UserService userService;
|
||||
|
||||
@IgnorePermissions
|
||||
@PostMapping("/api/auth")
|
||||
@ApiOperation(value = "jwt登录")
|
||||
public ResultVo auth(
|
||||
@ApiParam(value = "用户名", required = true) String username,
|
||||
@ApiParam(value = "密码", required = true) String password) {
|
||||
// 根据用户名获取系统用户数据
|
||||
User user = userService.getByName(username);
|
||||
if (user == null) {
|
||||
throw new ResultException(JwtResultEnums.AUTH_REQUEST_ERROR);
|
||||
} else if (user.getStatus().equals(StatusEnum.FREEZED.getCode())) {
|
||||
throw new ResultException(JwtResultEnums.AUTH_REQUEST_LOCKED);
|
||||
} else {
|
||||
// 对明文密码加密处理
|
||||
String encrypt = EncryptUtil.encrypt(password, user.getSalt());
|
||||
// 判断密码是否正确
|
||||
if (encrypt.equals(user.getPassword())) {
|
||||
String token = JwtUtil.getToken(username, properties.getSecret(), properties.getExpired());
|
||||
return ResultVoUtil.success("登录成功", token);
|
||||
} else {
|
||||
throw new ResultException(JwtResultEnums.AUTH_REQUEST_ERROR);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package com.linln.component.jwt.enums;
|
||||
|
||||
import com.linln.common.exception.interfaces.ResultInterface;
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* jwt结果集枚举
|
||||
* @author gion
|
||||
* @date 2019/4/13
|
||||
*/
|
||||
@Getter
|
||||
public enum JwtResultEnums implements ResultInterface {
|
||||
|
||||
/**
|
||||
* token问题
|
||||
*/
|
||||
TOKEN_ERROR(301, "token无效"),
|
||||
TOKEN_EXPIRED(302, "token已过期"),
|
||||
|
||||
/**
|
||||
* 账号问题
|
||||
*/
|
||||
AUTH_REQUEST_ERROR(401, "用户名或密码错误"),
|
||||
AUTH_REQUEST_LOCKED(402, "该账号已被冻结"),
|
||||
;
|
||||
|
||||
private Integer code;
|
||||
|
||||
private String message;
|
||||
|
||||
JwtResultEnums(Integer code, String message) {
|
||||
this.code = code;
|
||||
this.message = message;
|
||||
}
|
||||
}
|
||||
+69
@@ -0,0 +1,69 @@
|
||||
package com.linln.component.jwt.interceptor;
|
||||
|
||||
import com.auth0.jwt.exceptions.JWTVerificationException;
|
||||
import com.auth0.jwt.exceptions.TokenExpiredException;
|
||||
import com.linln.common.exception.ResultException;
|
||||
import com.linln.component.jwt.annotation.IgnorePermissions;
|
||||
import com.linln.component.jwt.config.properties.JwtProjectProperties;
|
||||
import com.linln.component.jwt.enums.JwtResultEnums;
|
||||
import com.linln.component.jwt.utlis.JwtUtil;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.method.HandlerMethod;
|
||||
import org.springframework.web.servlet.HandlerInterceptor;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
/**
|
||||
* jwt权限拦截器
|
||||
* @author gion
|
||||
* @date 2019/4/12
|
||||
*/
|
||||
@Component
|
||||
public class AuthenticationInterceptor implements HandlerInterceptor {
|
||||
|
||||
@Autowired
|
||||
private JwtProjectProperties jwtProperties;
|
||||
|
||||
@Override
|
||||
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
|
||||
// 如果不是映射到方法直接通过
|
||||
if (!(handler instanceof HandlerMethod)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// 判断请求映射的方式是否忽略权限验证
|
||||
HandlerMethod handlerMethod=(HandlerMethod) handler;
|
||||
Method method=handlerMethod.getMethod();
|
||||
if (method.isAnnotationPresent(IgnorePermissions.class)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// 获取请求对象头部token数据
|
||||
String token = JwtUtil.getRequestToken(request);
|
||||
|
||||
// 验证token数据是否正确
|
||||
try {
|
||||
JwtUtil.verifyToken(token, jwtProperties.getSecret());
|
||||
} catch (TokenExpiredException e) {
|
||||
throw new ResultException(JwtResultEnums.TOKEN_EXPIRED);
|
||||
} catch (JWTVerificationException e) {
|
||||
throw new ResultException(JwtResultEnums.TOKEN_ERROR);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
package com.linln.component.jwt.utlis;
|
||||
|
||||
import com.auth0.jwt.JWT;
|
||||
import com.auth0.jwt.JWTVerifier;
|
||||
import com.auth0.jwt.algorithms.Algorithm;
|
||||
import com.auth0.jwt.exceptions.JWTVerificationException;
|
||||
import com.auth0.jwt.exceptions.TokenExpiredException;
|
||||
import com.linln.common.exception.ResultException;
|
||||
import com.linln.common.utils.HttpServletUtil;
|
||||
import com.linln.common.utils.ToolUtil;
|
||||
import com.linln.component.jwt.enums.JwtResultEnums;
|
||||
import com.linln.modules.system.domain.User;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* @author gion
|
||||
* @date 2019/4/9
|
||||
*/
|
||||
public class JwtUtil {
|
||||
|
||||
/**
|
||||
* 生成JwtToken
|
||||
* @param username 用户名
|
||||
* @param secret 秘钥
|
||||
* @param amount 过期天数
|
||||
*/
|
||||
public static String getToken(String username, String secret, int amount){
|
||||
User user = new User();
|
||||
user.setUsername(username);
|
||||
return getToken(user, secret, amount);
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成JwtToken
|
||||
* @param user 用户对象
|
||||
* @param secret 秘钥
|
||||
* @param amount 过期天数
|
||||
*/
|
||||
public static String getToken(User user, String secret, int amount){
|
||||
// 过期时间
|
||||
Calendar ca = Calendar.getInstance();
|
||||
ca.add(Calendar.DATE, amount);
|
||||
|
||||
// 随机Claim
|
||||
String random = ToolUtil.getRandomString(6);
|
||||
|
||||
// 创建JwtToken对象
|
||||
String token="";
|
||||
token= JWT.create()
|
||||
// 用户名
|
||||
.withSubject(user.getUsername())
|
||||
// 发布时间
|
||||
.withIssuedAt(new Date())
|
||||
// 过期时间
|
||||
.withExpiresAt(ca.getTime())
|
||||
// 自定义随机Claim
|
||||
.withClaim("ran", random)
|
||||
.sign(getSecret(secret, random));
|
||||
|
||||
return token;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取请求对象中的token数据
|
||||
*/
|
||||
public static String getRequestToken(HttpServletRequest request){
|
||||
// 获取JwtTokens失败
|
||||
String authorization = request.getHeader("Authorization");
|
||||
if (authorization == null || !authorization.startsWith("Bearer ")) {
|
||||
throw new ResultException(JwtResultEnums.TOKEN_ERROR);
|
||||
}
|
||||
return authorization.substring(7);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前token中的用户名
|
||||
*/
|
||||
public static String getSubject(){
|
||||
HttpServletRequest request = HttpServletUtil.getRequest();
|
||||
String token = getRequestToken(request);
|
||||
return JWT.decode(token).getSubject();
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证JwtToken
|
||||
* @param token JwtToken数据
|
||||
* @return true 验证通过
|
||||
* @exception TokenExpiredException Token过期
|
||||
* @exception JWTVerificationException 令牌无效(验证不通过)
|
||||
*/
|
||||
public static void verifyToken(String token, String secret) throws JWTVerificationException {
|
||||
String ran = JWT.decode(token).getClaim("ran").asString();
|
||||
JWTVerifier jwtVerifier = JWT.require(getSecret(secret, ran)).build();
|
||||
jwtVerifier.verify(token);
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成Secret混淆数据
|
||||
*/
|
||||
private static Algorithm getSecret(String secret, String random){
|
||||
String salt = "君不见黄河之水天上来,奔流到海不复回。君不见高堂明镜悲白发,朝如青丝暮成雪。";
|
||||
//String salt = "元嘉草草,封狼居胥,赢得仓皇北顾。四十三年,望中犹记,烽火扬州路。可堪回首,佛狸祠下,一片神鸦社鼓。凭谁问、廉颇老矣,尚能饭否?";
|
||||
//String salt = "安能摧眉折腰事权贵,使我不得开心颜。";
|
||||
//String salt = "大江东去,浪淘尽,千古风流人物。故垒西边,人道是,三国周郎赤壁。乱石穿空,惊涛拍岸,卷起千堆雪。江山如画,一时多少豪杰。";
|
||||
return Algorithm.HMAC256(secret + salt + "(ノ ̄▽ ̄)ノ 皮一下" + random);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
|
||||
com.linln.component.jwt.config.JwtAutoConfig
|
||||
Reference in New Issue
Block a user