关于JWT的内容,请看以下链接,主要看它的原理,以及缺点!
/memmsc/article/details/78122931
步骤1:前端传userName+password到后端,后端为springcloud架构,经过网关的拦截器拦截请求,拦截器在项目启动的时候@Component进行加载。
步骤2:如果是第一次登陆,放行,进入JWT的加密生成Token阶段(还可以写入登陆用户的其他信息放在JWTmap中,之后可以利用Token来获取该用户信息),加密token需要一个随机数作为加密字段,将token的失效时间设置为一天,并且放到reids里面,设置该redis里面的token过期时间为30分钟,最后将Token返回给前端。
步骤3:以后任何的请求都带Token到后端去请求。
步骤4:拦截到非登陆请求,进行解密,鉴权,如果鉴权通过,更新redis里面token字段的失效时间,如果还有5分钟失效,再设置还有30分钟,目的就是让密码的过期时间变的活跃。
大致就是以上的过程,核心代码主要在网关拦截器解密鉴权和登陆接口的加密两部分
0,controller层的将得到的token做保存redis和设置过期时间的操作
-
compactJws = (username, password, userBean);
-
//将token存在redis里
-
().
set(
"token", compactJws);
-
//设置redis里面的数据失效时间为半小时
-
(
"token",
1800,
TimeUnit.
SECONDS);
1,登陆接口的加密:
-
package ;
-
-
import ;
-
import ;
-
import ;
-
import ;
-
import ;
-
import ;
-
import ;
-
-
import .Base64;
-
import ;
-
import ;
-
-
/**
-
* 用户身份验证Service
-
*/
-
@
Service(value =
"authService")
-
public
class AuthServiceImpl implements AuthService {
-
@
Override
-
public
String generateJwt(
String userName,
String userPassword,
UserBean userBean) {
-
// Base64编码后的secretKey
-
byte[] secretKey =
Base64.getEncoder().encode(
CommonConstants.
SECURITY_KEY.getBytes());
-
// 设置失效时间
-
DateTime expirationDate = new
DateTime().plusDays(
1);
-
//DateTime expirationDate = new DateTime().plusMinutes(30);
-
// Claims是需要保存到token中的信息,可以自定义,需要存什么就放什么,会保存到token的payload中
-
Map<
String,
Object> claims = new
HashMap<>();
-
// 用户角色
-
(
"role",
"user");
-
// 用户名
-
(
"userName", userName);
-
(
CommonConstants.
USER_ID, ());
-
(
"uuid",
UUID.randomUUID().
toString());
-
String compactJws =
Jwts.builder()
-
// 设置subject,一般是用户的唯一标识,比如用户对象的ID,用户名等,目前设置的是userCode
-
.setSubject(userName)
-
// 设置失效时间
-
.setExpiration(())
-
.addClaims(claims)
-
// 加密算法是HS512,加密解密统一就可以
-
.signWith(
SignatureAlgorithm.
HS512, secretKey)
-
.compact();
-
return compactJws;
-
}
-
-
}
以上常量类和pojo此处省略。。。。
2,网关拦截器解密鉴权:
-
package ;
-
-
import ;
-
import ;
-
import ;
-
import ;
-
import ;
-
import ;
-
import ;
-
import .*;
-
import ;
-
import ;
-
import ;
-
import ;
-
import ;
-
-
import ;
-
import .Base64;
-
-
@Component
-
public
class SecurityFilter extends ZuulFilter {
-
@Override
-
public String filterType() {
-
return FilterConstants.PRE_TYPE;
-
}
-
-
@Override
-
public int filterOrder() {
-
return FilterConstants.PRE_DECORATION_FILTER_ORDER -
1;
-
}
-
-
@Override
-
public boolean shouldFilter() {
-
RequestContext ctx = ();
-
HttpServletRequest request = ();
-
if (().toString().contains(
"loginInfo") || ().toString().contains(
"info")) {
-
return
false;
-
}
-
// TODO
-
return
true;
-
}
-
-
@Override
-
public Object run() {
-
RequestContext ctx = ();
-
HttpServletRequest request = ();
-
final String authorizationHeader = ();
-
-
if (().equals(())) {
-
return
null;
-
}
else {
-
if ((authorizationHeader) || !()) {
-
// Missing or invalid Authorization header
-
ErrorResponseMap errorResponseMap = (
null,
"Missing or invalid Authorization header!",
-
ErrorCode.INVALID_AUTHORIZATION_HEADER, request,
null);
-
denyAccess(ctx,errorResponseMap);
-
return (errorResponseMap);
-
}
-
final String token = (
7);
-
try {
-
byte[] secretKey = ().encode(CommonConstants.SECURITY_KEY.getBytes());
-
Claims claims = ().setSigningKey(secretKey).parseClaimsJws(token).getBody();
-
if (claims !=
null) {
-
//获取redis里面数据的存活时间
-
Long expirationDate = (
"token",);
-
//如果还剩余5分钟,重置redis里面数据的存活时间
-
if(expirationDate >
300){
-
(
"token",
1800,);
-
}
else {
-
ErrorResponseMap errorResponseMap = new ErrorResponseMap();
-
Error error = new Error(
null,
"Token expired!",
"",
1003,
"");
-
(
false);
-
(
null);
-
(error);
-
denyAccess(ctx,errorResponseMap);
-
return (errorResponseMap);
-
}
-
String userName = (String) claims.
get(CommonConstants.USER_CODE);
-
Integer userId = (Integer) claims.
get(CommonConstants.USER_ID);
-
(CommonConstants.USER_CODE, userName);
-
(CommonConstants.USER_ID, (userId));
-
}
-
}
catch (MalformedJwtException ex) {
-
ErrorResponseMap errorResponseMap = (
null,
"Invalid token!",
-
ErrorCode.INVALID_AUTHORIZATION_HEADER, request, ex);
-
denyAccess(ctx,errorResponseMap);
-
return (errorResponseMap);
-
}
catch (SignatureException ex) {
-
ErrorResponseMap errorResponseMap = (
null,
"Token Signature error!",
-
ErrorCode.SIGNATURE_EXCEPTION, request, ex);
-
denyAccess(ctx,errorResponseMap);
-
return (errorResponseMap);
-
}
catch (ExpiredJwtException ex) {
-
ErrorResponseMap errorResponseMap = (
null,
"Token expired!",
-
ErrorCode.EXPIRED_JWT_EXCEPTION, request, ex);
-
denyAccess(ctx,errorResponseMap);
-
return (errorResponseMap);
-
}
-
}
-
return
null;
-
}
-
-
private void denyAccess(RequestContext ctx, ErrorResponseMap authResult) {
-
String result = (authResult);
-
(
false);
-
(
401);
-
try {
-
().getWriter().write(result);
-
}
catch (Exception e){}
-
}
-
}
以上代码是核心代码,下面是自己项目中涉及到的异常包装类,以及util类,可以不管下面的,直接去封装
以上涉及到的类:
(1)ErrorResponseMap
-
package
com
.movitech
.commons
.dto;
-
-
import
com
.fasterxml
.jackson
.annotation
.JsonProperty;
-
import
com
.movitech
.commons
.exception
.Error;
-
import
lombok
.Getter;
-
import
lombok
.Setter;
-
-
@
Getter
-
@Setter
-
public class ErrorResponseMap extends ResponseMap {
-
@
JsonProperty(
value =
"error")
-
private Error error;
-
@
JsonProperty(
value =
"stackTrace")
-
private String stackTrace;
-
}
(1.1)Error
-
package ;
-
-
import ;
-
import ;
-
import ;
-
import ;
-
-
@Getter
-
@Setter
-
@NoArgsConstructor
-
@AllArgsConstructor
-
public
class Error {
-
// 标准的 Http status code
-
private Integer httpStatusCode;
-
// 自定义的错误说明
-
private String errorMsg;
-
// 异常信息
-
private String exceptionMsg;
-
// 自定义的错误代码
-
private Integer errorCode;
-
// 异常的类名
-
private String exceptionClassName;
-
}
(2)ErrorCode
-
package ;
-
-
/**
-
* 自定义的错误代码的枚举
-
*/
-
public
enum ErrorCode {
-
// Token 签名错误
-
SIGNATURE_EXCEPTION(
1000),
-
// Token 过期
-
EXPIRED_JWT_EXCEPTION(
1001),
-
// 无效的Authorization header
-
INVALID_AUTHORIZATION_HEADER(
1002);
-
private Integer errorCode;
-
ErrorCode(Integer errorCode) {
-
this.errorCode = errorCode;
-
}
-
-
@Override
-
public String toString() {
-
return ();
-
}
-
-
public Integer value() {
-
return errorCode;
-
}
-
}
(3)JsonUtil
-
package ;
-
-
import ;
-
import .*;
-
import .Jackson2ObjectMapperBuilder;
-
import ;
-
import ;
-
-
import ;
-
-
/**
-
* Json序列化和反序列化
-
*/
-
@Component
-
public
class JsonUtil
-
{
-
public static ObjectMapper mapper;
-
/* static {
-
dao = new ObjectMapper();
-
(SerializationFeature.WRAP_ROOT_VALUE,true);
-
(DeserializationFeature.UNWRAP_ROOT_VALUE, true);
-
}*/
-
-
public JsonUtil(Jackson2ObjectMapperBuilder jackson2ObjectMapperBuilder) {
-
mapper = ();
-
}
-
-
public static String serializeToString(Object
object) {
-
return serializeToString(
object,
false);
-
}
-
-
public static String serializeToString(Object
object,
Boolean rootValueState) {
-
SerializationConfig serializationConfig = ();
-
(SerializationFeature.WRAP_ROOT_VALUE,rootValueState);
-
if (
object !=
null) {
-
try {
-
return (
object);
-
}
catch (JsonProcessingException e) {
-
();
-
}
finally {
-
(serializationConfig);
-
}
-
}
-
return
"";
-
}
-
-
public static byte[] serializeToBytes(Object
object) {
-
if (
object !=
null) {
-
try {
-
return (
object);
-
}
catch (JsonProcessingException e) {
-
();
-
}
-
}
-
return
null;
-
}
-
-
/**
-
* 反序列化Json数据
-
* @param jsonData Json数据字符串
-
* @param valueType 反序列化的类型
-
* @param rootValueState 是否解析Json root name
-
* @param <T>
-
* @return 反序列化后的POJO
-
*/
-
public static <T> T deserialize(String jsonData,Class<T> valueType,
Boolean rootValueState) {
-
if ((jsonData) || rootValueState ==
null) {
-
return
null;
-
}
-
DeserializationConfig deserializationConfig = ();
-
(DeserializationFeature.UNWRAP_ROOT_VALUE,rootValueState);
-
try {
-
return (jsonData, valueType);
-
}
catch (IOException e) {
-
();
-
}
finally {
-
(deserializationConfig);
-
}
-
return
null;
-
}
-
-
/**
-
* 反序列化Json数据,默认解析Json root name
-
* @param jsonData Json数据字符串
-
* @param valueType 反序列化的类型
-
* @param <T>
-
* @return 反序列化后的POJO
-
*/
-
public static <T> T deserialize(String jsonData,Class<T> valueType) {
-
return deserialize(jsonData, valueType,
true);
-
}
-
-
public static JavaType getCollectionType(Class<?> collectionClass, Class<?>... elementClasses) {
-
return ().constructParametricType(collectionClass, elementClasses);
-
}
-
-
/**
-
* 用Json数据中的key获取对应的value
-
* @param jsonString json数据字符串
-
* @param field 需要取值的字段
-
* @param rootValueState 是否解析Json root name
-
* @return 字段对应的值
-
*/
-
public static String getValue(String jsonString,String field,
Boolean rootValueState) {
-
JsonNode node = getJsonNode(jsonString,field,rootValueState);
-
return node ==
null ?
"" : ();
-
}
-
-
/**
-
* 用Json数据中的key获取对应的value, 默认解析Json root name
-
* @param jsonString json数据字符串
-
* @param field 需要取值的字段
-
* @return 字段对应的值
-
*/
-
public static String getValue(String jsonString,String field) {
-
return getValue(jsonString,field,
true);
-
}
-
-
/**
-
* 用Json数据中的key获取对应的value
-
* @param jsonString json数据字符串
-
* @param field 需要取值的字段
-
* @param rootValueState 是否解析Json root name
-
* @return 字段对应的值
-
*/
-
public static JsonNode getJsonNode(String jsonString, String field,
Boolean rootValueState) {
-
if ((jsonString) || (field) || rootValueState ==
null) {
-
return
null;
-
}
-
// 准备工作 传入vo请参照第一篇里面的实体。此处不再重新贴上代码 浪费大家时间
-
JsonNode node =
null;
// 这里的JsonNode和XML里面的Node很像
-
// 默认的反序列化配置
-
DeserializationConfig deserializationConfig = ();
-
(DeserializationFeature.UNWRAP_ROOT_VALUE,rootValueState);
-
try {
-
node = (jsonString);
-
}
catch (IOException e) {
-
();
-
return
null;
-
}
finally {
-
(deserializationConfig);
-
}
-
return node.
get(field) ==
null ?
null : node.
get(field);
-
}
-
}
(4)ResponseUtil
-
package ;
-
-
import ;
-
import ;
-
import ;
-
import ;
-
import ;
-
-
import ;
-
-
public
class ResponseUtil {
-
public static ResponseEntity createResponseEntity(String errorMsg, ErrorCode errorCode, HttpServletRequest request, Throwable ex) {
-
HttpStatus status = getStatus(request);
-
ErrorResponseMap errorResponseMap = createErrorResponse(status, errorMsg, errorCode, request, ex);
-
return
new ResponseEntity<>(errorResponseMap, status);
-
}
-
-
public static ErrorResponseMap createErrorResponse(HttpStatus status, String errorMsg, ErrorCode errorCode, HttpServletRequest request, Throwable ex) {
-
if (status ==
null) {
-
status = getStatus(request);
-
}
-
ErrorResponseMap errorResponseMap =
new ErrorResponseMap();
-
Error error =
new Error((), errorMsg, ex ==
null ?
"" : (),
-
errorCode ==
null ? HttpStatus.INTERNAL_SERVER_ERROR.value() : (), ex ==
null ?
"" : ().getCanonicalName());
-
(
false);
-
(());
-
(error);
-
// String stackTrace = ((), "hahaha");
-
// (stackTrace);
-
return errorResponseMap;
-
}
-
-
public static HttpStatus getStatus(HttpServletRequest request) {
-
Integer statusCode = (Integer) (
".status_code");
-
if (statusCode ==
null) {
-
return HttpStatus.INTERNAL_SERVER_ERROR;
-
}
-
return (statusCode);
-
}
-
}
文章转载自:/qq_34707991/article/details/82898187