Commit 997d8e63 by wilmiam

1.0.0

parent b762e622
...@@ -40,8 +40,6 @@ public class LoginProperties { ...@@ -40,8 +40,6 @@ public class LoginProperties {
private LoginCode loginCode; private LoginCode loginCode;
public static final String cacheKey = "USER-LOGIN-DATA";
public boolean isSingleLogin() { public boolean isSingleLogin() {
return singleLogin; return singleLogin;
} }
......
...@@ -19,6 +19,7 @@ import com.zq.admin.modules.security.service.OnlineUserService; ...@@ -19,6 +19,7 @@ import com.zq.admin.modules.security.service.OnlineUserService;
import com.zq.admin.modules.security.service.UserCacheManager; import com.zq.admin.modules.security.service.UserCacheManager;
import com.zq.common.annotation.AnonymousAccess; import com.zq.common.annotation.AnonymousAccess;
import com.zq.common.config.security.SecurityProperties; import com.zq.common.config.security.SecurityProperties;
import com.zq.common.config.security.TokenProvider;
import com.zq.common.utils.RequestMethodEnum; import com.zq.common.utils.RequestMethodEnum;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContext;
......
...@@ -18,6 +18,7 @@ package com.zq.admin.config.security; ...@@ -18,6 +18,7 @@ package com.zq.admin.config.security;
import com.zq.admin.modules.security.service.OnlineUserService; import com.zq.admin.modules.security.service.OnlineUserService;
import com.zq.admin.modules.security.service.UserCacheManager; import com.zq.admin.modules.security.service.UserCacheManager;
import com.zq.common.config.security.SecurityProperties; import com.zq.common.config.security.SecurityProperties;
import com.zq.common.config.security.TokenProvider;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import org.springframework.security.config.annotation.SecurityConfigurerAdapter; import org.springframework.security.config.annotation.SecurityConfigurerAdapter;
import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.builders.HttpSecurity;
......
...@@ -19,6 +19,7 @@ import cn.hutool.core.util.StrUtil; ...@@ -19,6 +19,7 @@ import cn.hutool.core.util.StrUtil;
import com.zq.admin.modules.security.service.OnlineUserService; import com.zq.admin.modules.security.service.OnlineUserService;
import com.zq.admin.modules.security.service.UserCacheManager; import com.zq.admin.modules.security.service.UserCacheManager;
import com.zq.common.config.security.SecurityProperties; import com.zq.common.config.security.SecurityProperties;
import com.zq.common.config.security.TokenProvider;
import com.zq.common.context.ContextUtils; import com.zq.common.context.ContextUtils;
import com.zq.common.vo.OnlineUserDto; import com.zq.common.vo.OnlineUserDto;
import io.jsonwebtoken.ExpiredJwtException; import io.jsonwebtoken.ExpiredJwtException;
......
package com.zq.admin.config.security;/* // package com.zq.admin.config.security;/*
* Copyright 2019-2020 Zheng Jie // * Copyright 2019-2020 Zheng Jie
* // *
* Licensed under the Apache License, Version 2.0 (the "License"); // * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. // * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at // * You may obtain a copy of the License at
* // *
* http://www.apache.org/licenses/LICENSE-2.0 // * http://www.apache.org/licenses/LICENSE-2.0
* // *
* Unless required by applicable law or agreed to in writing, software // * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, // * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and // * See the License for the specific language governing permissions and
* limitations under the License. // * limitations under the License.
*/ // */
//
import cn.hutool.core.date.DateField; // import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateUtil; // import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.IdUtil; // import cn.hutool.core.util.IdUtil;
import com.zq.common.config.redis.RedisUtils; // import com.zq.common.config.redis.RedisUtils;
import com.zq.common.config.security.SecurityProperties; // import com.zq.common.config.security.SecurityProperties;
import io.jsonwebtoken.Claims; // import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts; // import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm; // import io.jsonwebtoken.SignatureAlgorithm;
import lombok.RequiredArgsConstructor; // import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; // import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils; // import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.InitializingBean; // import org.springframework.beans.factory.InitializingBean;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; // import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication; // import org.springframework.security.core.Authentication;
import org.springframework.security.core.userdetails.User; // import org.springframework.security.core.userdetails.User;
import org.springframework.stereotype.Component; // import org.springframework.stereotype.Component;
//
import javax.crypto.spec.SecretKeySpec; // import javax.crypto.spec.SecretKeySpec;
import javax.servlet.http.HttpServletRequest; // import javax.servlet.http.HttpServletRequest;
import javax.xml.bind.DatatypeConverter; // import javax.xml.bind.DatatypeConverter;
import java.security.Key; // import java.security.Key;
import java.util.ArrayList; // import java.util.ArrayList;
import java.util.Date; // import java.util.Date;
import java.util.concurrent.TimeUnit; // import java.util.concurrent.TimeUnit;
//
/** // /**
* @author / // * @author /
*/ // */
@Slf4j // @Slf4j
@Component // @Component
@RequiredArgsConstructor // @RequiredArgsConstructor
public class TokenProvider implements InitializingBean { // public class TokenProvider implements InitializingBean {
//
private final RedisUtils redisUtils; // private final RedisUtils redisUtils;
private final SecurityProperties properties; // private final SecurityProperties properties;
//
public static final String AUTHORITIES_KEY = "auth"; // public static final String AUTHORITIES_KEY = "auth";
private static Key key; // private static Key key;
private static SignatureAlgorithm signatureAlgorithm; // private static SignatureAlgorithm signatureAlgorithm;
//
@Override // @Override
public void afterPropertiesSet() { // public void afterPropertiesSet() {
signatureAlgorithm = SignatureAlgorithm.HS512; // signatureAlgorithm = SignatureAlgorithm.HS512;
byte[] keyBytes = DatatypeConverter.parseBase64Binary(properties.getBase64Secret()); // byte[] keyBytes = DatatypeConverter.parseBase64Binary(properties.getBase64Secret());
key = new SecretKeySpec(keyBytes, signatureAlgorithm.getJcaName()); // key = new SecretKeySpec(keyBytes, signatureAlgorithm.getJcaName());
} // }
//
public static String createToken(Authentication authentication) { // public static String createToken(Authentication authentication) {
return Jwts.builder() // return Jwts.builder()
.claim(AUTHORITIES_KEY, authentication.getName()) // .claim(AUTHORITIES_KEY, authentication.getName())
.setSubject(authentication.getName()) // .setSubject(authentication.getName())
.signWith(signatureAlgorithm, key) // .signWith(signatureAlgorithm, key)
// 加入ID确保生成的 Token 都不一致 // // 加入ID确保生成的 Token 都不一致
.setId(IdUtil.simpleUUID()) // .setId(IdUtil.simpleUUID())
.compact(); // .compact();
} // }
//
public Claims getClaims(String token) { // public Claims getClaims(String token) {
return Jwts.parser() // return Jwts.parser()
.setSigningKey(DatatypeConverter.parseBase64Binary(properties.getBase64Secret())) // .setSigningKey(DatatypeConverter.parseBase64Binary(properties.getBase64Secret()))
.parseClaimsJws(token) // .parseClaimsJws(token)
.getBody(); // .getBody();
} // }
//
public Authentication getAuthentication(String token) { // public Authentication getAuthentication(String token) {
Claims claims = getClaims(token); // Claims claims = getClaims(token);
User principal = new User(claims.getSubject(), "******", new ArrayList<>()); // User principal = new User(claims.getSubject(), "******", new ArrayList<>());
return new UsernamePasswordAuthenticationToken(principal, token, new ArrayList<>()); // return new UsernamePasswordAuthenticationToken(principal, token, new ArrayList<>());
} // }
//
/** // /**
* @param token 需要检查的token // * @param token 需要检查的token
*/ // */
public void checkRenewal(String token) { // public void checkRenewal(String token) {
// 判断是否续期token,计算token的过期时间 // // 判断是否续期token,计算token的过期时间
long time = redisUtils.getExpire(properties.getOnlineKey() + token) * 1000; // long time = redisUtils.getExpire(properties.getOnlineKey() + token) * 1000;
Date expireDate = DateUtil.offset(new Date(), DateField.MILLISECOND, (int) time); // Date expireDate = DateUtil.offset(new Date(), DateField.MILLISECOND, (int) time);
// 判断当前时间与过期时间的时间差 // // 判断当前时间与过期时间的时间差
long differ = expireDate.getTime() - System.currentTimeMillis(); // long differ = expireDate.getTime() - System.currentTimeMillis();
// 如果在续期检查的范围内,则续期 // // 如果在续期检查的范围内,则续期
if (differ <= properties.getDetect()) { // if (differ <= properties.getDetect()) {
long renew = time + properties.getRenew(); // long renew = time + properties.getRenew();
redisUtils.expire(properties.getOnlineKey() + token, renew, TimeUnit.MILLISECONDS); // redisUtils.expire(properties.getOnlineKey() + token, renew, TimeUnit.MILLISECONDS);
} // }
} // }
//
public String getToken(HttpServletRequest request) { // public String getToken(HttpServletRequest request) {
String bearerToken = request.getHeader(properties.getHeader()); // String bearerToken = request.getHeader(properties.getHeader());
if (StringUtils.isBlank(bearerToken)) { // if (StringUtils.isBlank(bearerToken)) {
return null; // return null;
} // }
if (bearerToken.startsWith(properties.getTokenStartWith())) { // if (bearerToken.startsWith(properties.getTokenStartWith())) {
// 去掉令牌前缀 // // 去掉令牌前缀
return bearerToken.replace(properties.getTokenStartWith(), ""); // return bearerToken.replace(properties.getTokenStartWith(), "");
} else { // } else {
log.debug("非法Token:{}", bearerToken); // log.debug("非法Token:{}", bearerToken);
} // }
return null; // return null;
} // }
//
} // }
...@@ -186,7 +186,7 @@ public class DeployServiceImpl implements DeployService { ...@@ -186,7 +186,7 @@ public class DeployServiceImpl implements DeployService {
private void sleep(int second) { private void sleep(int second) {
try { try {
Thread.sleep(second * 1000); Thread.sleep(second * 1000L);
} catch (InterruptedException e) { } catch (InterruptedException e) {
log.error(e.getMessage(), e); log.error(e.getMessage(), e);
} }
...@@ -219,7 +219,6 @@ public class DeployServiceImpl implements DeployService { ...@@ -219,7 +219,6 @@ public class DeployServiceImpl implements DeployService {
private void stopApp(int port, ExecuteShellUtil executeShellUtil) { private void stopApp(int port, ExecuteShellUtil executeShellUtil) {
//发送停止命令 //发送停止命令
executeShellUtil.execute(String.format("lsof -i :%d|grep -v \"PID\"|awk '{print \"kill -9\",$2}'|sh", port)); executeShellUtil.execute(String.format("lsof -i :%d|grep -v \"PID\"|awk '{print \"kill -9\",$2}'|sh", port));
} }
/** /**
......
...@@ -20,7 +20,6 @@ import com.wf.captcha.base.Captcha; ...@@ -20,7 +20,6 @@ import com.wf.captcha.base.Captcha;
import com.zq.admin.config.RsaProperties; import com.zq.admin.config.RsaProperties;
import com.zq.admin.config.bean.LoginCodeEnum; import com.zq.admin.config.bean.LoginCodeEnum;
import com.zq.admin.config.bean.LoginProperties; import com.zq.admin.config.bean.LoginProperties;
import com.zq.admin.config.security.TokenProvider;
import com.zq.admin.exception.BadRequestException; import com.zq.admin.exception.BadRequestException;
import com.zq.admin.modules.security.service.OnlineUserService; import com.zq.admin.modules.security.service.OnlineUserService;
import com.zq.admin.modules.security.service.dto.AuthUserDto; import com.zq.admin.modules.security.service.dto.AuthUserDto;
...@@ -32,6 +31,7 @@ import com.zq.common.annotation.rest.AnonymousGetMapping; ...@@ -32,6 +31,7 @@ import com.zq.common.annotation.rest.AnonymousGetMapping;
import com.zq.common.annotation.rest.AnonymousPostMapping; import com.zq.common.annotation.rest.AnonymousPostMapping;
import com.zq.common.config.redis.RedisUtils; import com.zq.common.config.redis.RedisUtils;
import com.zq.common.config.security.SecurityProperties; import com.zq.common.config.security.SecurityProperties;
import com.zq.common.config.security.TokenProvider;
import io.swagger.annotations.Api; import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
......
...@@ -16,8 +16,8 @@ ...@@ -16,8 +16,8 @@
package com.zq.admin.modules.security.service; package com.zq.admin.modules.security.service;
import cn.hutool.core.util.RandomUtil; import cn.hutool.core.util.RandomUtil;
import com.zq.admin.config.bean.LoginProperties;
import com.zq.admin.modules.security.service.dto.JwtUserDto; import com.zq.admin.modules.security.service.dto.JwtUserDto;
import com.zq.common.config.redis.BaseCacheKeys;
import com.zq.common.config.redis.RedisUtils; import com.zq.common.config.redis.RedisUtils;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
...@@ -48,7 +48,7 @@ public class UserCacheManager { ...@@ -48,7 +48,7 @@ public class UserCacheManager {
public JwtUserDto getUserCache(String userName) { public JwtUserDto getUserCache(String userName) {
if (StringUtils.isNotEmpty(userName)) { if (StringUtils.isNotEmpty(userName)) {
// 获取数据 // 获取数据
Object obj = redisUtils.hget(LoginProperties.cacheKey, userName); Object obj = redisUtils.hget(BaseCacheKeys.USER_DATA_MAP_KEY, userName);
if (obj != null) { if (obj != null) {
return (JwtUserDto) obj; return (JwtUserDto) obj;
} }
...@@ -66,7 +66,7 @@ public class UserCacheManager { ...@@ -66,7 +66,7 @@ public class UserCacheManager {
if (StringUtils.isNotEmpty(userName)) { if (StringUtils.isNotEmpty(userName)) {
// 添加数据, 避免数据同时过期 // 添加数据, 避免数据同时过期
long time = idleTime + RandomUtil.randomInt(900, 1800); long time = idleTime + RandomUtil.randomInt(900, 1800);
redisUtils.hset(LoginProperties.cacheKey, userName, user, time); redisUtils.hset(BaseCacheKeys.USER_DATA_MAP_KEY, userName, user, time);
} }
} }
...@@ -80,8 +80,8 @@ public class UserCacheManager { ...@@ -80,8 +80,8 @@ public class UserCacheManager {
public void cleanUserCache(String userName) { public void cleanUserCache(String userName) {
if (StringUtils.isNotEmpty(userName)) { if (StringUtils.isNotEmpty(userName)) {
// 清除数据 // 清除数据
redisUtils.hdel(LoginProperties.cacheKey, userName); redisUtils.hdel(BaseCacheKeys.USER_DATA_MAP_KEY, userName);
} }
} }
} }
\ No newline at end of file
...@@ -18,6 +18,7 @@ package com.zq.user.config; ...@@ -18,6 +18,7 @@ package com.zq.user.config;
import com.zq.common.annotation.AnonymousAccess; import com.zq.common.annotation.AnonymousAccess;
import com.zq.common.config.redis.RedisUtils; import com.zq.common.config.redis.RedisUtils;
import com.zq.common.config.security.SecurityProperties; import com.zq.common.config.security.SecurityProperties;
import com.zq.common.config.security.TokenProvider;
import com.zq.common.utils.RequestMethodEnum; import com.zq.common.utils.RequestMethodEnum;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContext;
......
...@@ -17,6 +17,7 @@ package com.zq.user.config; ...@@ -17,6 +17,7 @@ package com.zq.user.config;
import com.zq.common.config.redis.RedisUtils; import com.zq.common.config.redis.RedisUtils;
import com.zq.common.config.security.SecurityProperties; import com.zq.common.config.security.SecurityProperties;
import com.zq.common.config.security.TokenProvider;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import org.springframework.security.config.annotation.SecurityConfigurerAdapter; import org.springframework.security.config.annotation.SecurityConfigurerAdapter;
import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.builders.HttpSecurity;
......
...@@ -16,8 +16,10 @@ ...@@ -16,8 +16,10 @@
package com.zq.user.config; package com.zq.user.config;
import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.StrUtil;
import com.zq.common.config.redis.BaseCacheKeys;
import com.zq.common.config.redis.RedisUtils; import com.zq.common.config.redis.RedisUtils;
import com.zq.common.config.security.SecurityProperties; import com.zq.common.config.security.SecurityProperties;
import com.zq.common.config.security.TokenProvider;
import com.zq.common.context.ContextUtils; import com.zq.common.context.ContextUtils;
import com.zq.common.vo.OnlineUserDto; import com.zq.common.vo.OnlineUserDto;
import io.jsonwebtoken.ExpiredJwtException; import io.jsonwebtoken.ExpiredJwtException;
...@@ -74,7 +76,8 @@ public class TokenFilter extends GenericFilterBean { ...@@ -74,7 +76,8 @@ public class TokenFilter extends GenericFilterBean {
cleanUserCache = true; cleanUserCache = true;
} finally { } finally {
if (cleanUserCache || Objects.isNull(onlineUserDto)) { if (cleanUserCache || Objects.isNull(onlineUserDto)) {
// userCacheClean.cleanUserCache(String.valueOf(tokenProvider.getClaims(token).get(TokenProvider.AUTHORITIES_KEY))); String username = String.valueOf(tokenProvider.getClaims(token).get(TokenProvider.AUTHORITIES_KEY));
redisUtils.hdel(BaseCacheKeys.USER_DATA_MAP_KEY, username);
} }
} }
if (onlineUserDto != null && StringUtils.isNotBlank(token)) { if (onlineUserDto != null && StringUtils.isNotBlank(token)) {
......
package com.zq.user.config;/* // package com.zq.user.config;/*
* Copyright 2019-2020 Zheng Jie // * Copyright 2019-2020 Zheng Jie
* // *
* Licensed under the Apache License, Version 2.0 (the "License"); // * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. // * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at // * You may obtain a copy of the License at
* // *
* http://www.apache.org/licenses/LICENSE-2.0 // * http://www.apache.org/licenses/LICENSE-2.0
* // *
* Unless required by applicable law or agreed to in writing, software // * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, // * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and // * See the License for the specific language governing permissions and
* limitations under the License. // * limitations under the License.
*/ // */
//
import cn.hutool.core.date.DateField; // import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateUtil; // import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.IdUtil; // import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjectUtil; // import cn.hutool.core.util.ObjectUtil;
import com.zq.common.config.redis.RedisUtils; // import com.zq.common.config.redis.RedisUtils;
import com.zq.common.config.security.SecurityProperties; // import com.zq.common.config.security.SecurityProperties;
import io.jsonwebtoken.Claims; // import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts; // import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm; // import io.jsonwebtoken.SignatureAlgorithm;
import lombok.RequiredArgsConstructor; // import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; // import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils; // import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.InitializingBean; // import org.springframework.beans.factory.InitializingBean;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; // import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication; // import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority; // import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority; // import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.User; // import org.springframework.security.core.userdetails.User;
import org.springframework.stereotype.Component; // import org.springframework.stereotype.Component;
//
import javax.crypto.spec.SecretKeySpec; // import javax.crypto.spec.SecretKeySpec;
import javax.servlet.http.HttpServletRequest; // import javax.servlet.http.HttpServletRequest;
import javax.xml.bind.DatatypeConverter; // import javax.xml.bind.DatatypeConverter;
import java.security.Key; // import java.security.Key;
import java.util.Arrays; // import java.util.Arrays;
import java.util.Collection; // import java.util.Collection;
import java.util.Collections; // import java.util.Collections;
import java.util.Date; // import java.util.Date;
import java.util.concurrent.TimeUnit; // import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors; // import java.util.stream.Collectors;
//
/** // /**
* @author / // * @author /
*/ // */
@Slf4j // @Slf4j
@Component // @Component
@RequiredArgsConstructor // @RequiredArgsConstructor
public class TokenProvider implements InitializingBean { // public class TokenProvider implements InitializingBean {
//
private final RedisUtils redisUtils; // private final RedisUtils redisUtils;
private final SecurityProperties properties; // private final SecurityProperties properties;
//
public static final String AUTHORITIES_KEY = "auth"; // public static final String AUTHORITIES_KEY = "auth";
private static Key key; // private static Key key;
private static SignatureAlgorithm signatureAlgorithm; // private static SignatureAlgorithm signatureAlgorithm;
//
@Override // @Override
public void afterPropertiesSet() { // public void afterPropertiesSet() {
signatureAlgorithm = SignatureAlgorithm.HS512; // signatureAlgorithm = SignatureAlgorithm.HS512;
byte[] keyBytes = DatatypeConverter.parseBase64Binary(properties.getBase64Secret()); // byte[] keyBytes = DatatypeConverter.parseBase64Binary(properties.getBase64Secret());
key = new SecretKeySpec(keyBytes, signatureAlgorithm.getJcaName()); // key = new SecretKeySpec(keyBytes, signatureAlgorithm.getJcaName());
} // }
//
public static String createToken(Authentication authentication) { // public static String createToken(Authentication authentication) {
String authorities = authentication.getAuthorities().stream() // String authorities = authentication.getAuthorities().stream()
.map(GrantedAuthority::getAuthority) // .map(GrantedAuthority::getAuthority)
.collect(Collectors.joining(",")); // .collect(Collectors.joining(","));
//
return Jwts.builder() // return Jwts.builder()
.setSubject(authentication.getName()) // .setSubject(authentication.getName())
.claim(AUTHORITIES_KEY, authorities) // .claim(AUTHORITIES_KEY, authorities)
.signWith(signatureAlgorithm, key) // .signWith(signatureAlgorithm, key)
// 加入ID确保生成的 Token 都不一致 // // 加入ID确保生成的 Token 都不一致
.setId(IdUtil.simpleUUID()) // .setId(IdUtil.simpleUUID())
.compact(); // .compact();
} // }
//
public Claims getClaims(String token) { // public Claims getClaims(String token) {
return Jwts.parser() // return Jwts.parser()
.setSigningKey(DatatypeConverter.parseBase64Binary(properties.getBase64Secret())) // .setSigningKey(DatatypeConverter.parseBase64Binary(properties.getBase64Secret()))
.parseClaimsJws(token) // .parseClaimsJws(token)
.getBody(); // .getBody();
} // }
//
public Authentication getAuthentication(String token) { // public Authentication getAuthentication(String token) {
Claims claims = Jwts.parser() // Claims claims = getClaims(token);
.setSigningKey(DatatypeConverter.parseBase64Binary(properties.getBase64Secret())) //
.parseClaimsJws(token) // // fix bug: 当前用户如果没有任何权限时,在输入用户名后,刷新验证码会抛IllegalArgumentException
.getBody(); // Object authoritiesStr = claims.get(AUTHORITIES_KEY);
// Collection<? extends GrantedAuthority> authorities =
// fix bug: 当前用户如果没有任何权限时,在输入用户名后,刷新验证码会抛IllegalArgumentException // ObjectUtil.isNotEmpty(authoritiesStr) ?
Object authoritiesStr = claims.get(AUTHORITIES_KEY); // Arrays.stream(authoritiesStr.toString().split(","))
Collection<? extends GrantedAuthority> authorities = // .map(SimpleGrantedAuthority::new)
ObjectUtil.isNotEmpty(authoritiesStr) ? // .collect(Collectors.toList()) : Collections.emptyList();
Arrays.stream(authoritiesStr.toString().split(",")) //
.map(SimpleGrantedAuthority::new) // User principal = new User(claims.getSubject(), "******", authorities);
.collect(Collectors.toList()) : Collections.emptyList(); //
// return new UsernamePasswordAuthenticationToken(principal, token, authorities);
User principal = new User(claims.getSubject(), "******", authorities); // }
//
return new UsernamePasswordAuthenticationToken(principal, token, authorities); // /**
} // * @param token 需要检查的token
// */
/** // public void checkRenewal(String token) {
* @param token 需要检查的token // // 判断是否续期token,计算token的过期时间
*/ // long time = redisUtils.getExpire(properties.getOnlineKey() + token) * 1000;
public void checkRenewal(String token) { // Date expireDate = DateUtil.offset(new Date(), DateField.MILLISECOND, (int) time);
// 判断是否续期token,计算token的过期时间 // // 判断当前时间与过期时间的时间差
long time = redisUtils.getExpire(properties.getOnlineKey() + token) * 1000; // long differ = expireDate.getTime() - System.currentTimeMillis();
Date expireDate = DateUtil.offset(new Date(), DateField.MILLISECOND, (int) time); // // 如果在续期检查的范围内,则续期
// 判断当前时间与过期时间的时间差 // if (differ <= properties.getDetect()) {
long differ = expireDate.getTime() - System.currentTimeMillis(); // long renew = time + properties.getRenew();
// 如果在续期检查的范围内,则续期 // redisUtils.expire(properties.getOnlineKey() + token, renew, TimeUnit.MILLISECONDS);
if (differ <= properties.getDetect()) { // }
long renew = time + properties.getRenew(); // }
redisUtils.expire(properties.getOnlineKey() + token, renew, TimeUnit.MILLISECONDS); //
} // public String getToken(HttpServletRequest request) {
} // String bearerToken = request.getHeader(properties.getHeader());
// if (StringUtils.isBlank(bearerToken)) {
public String getToken(HttpServletRequest request) { // return null;
String bearerToken = request.getHeader(properties.getHeader()); // }
if (StringUtils.isBlank(bearerToken)) { // if (bearerToken.startsWith(properties.getTokenStartWith())) {
return null; // // 去掉令牌前缀
} // return bearerToken.replace(properties.getTokenStartWith(), "");
if (bearerToken.startsWith(properties.getTokenStartWith())) { // } else {
// 去掉令牌前缀 // log.debug("非法Token:{}", bearerToken);
return bearerToken.replace(properties.getTokenStartWith(), ""); // }
} else { // return null;
log.debug("非法Token:{}", bearerToken); // }
} //
return null; // }
}
}
...@@ -19,6 +19,8 @@ public abstract class BaseCacheKeys { ...@@ -19,6 +19,8 @@ public abstract class BaseCacheKeys {
private static final String RATE_LIMIT = PREFIX + "rate-limit."; private static final String RATE_LIMIT = PREFIX + "rate-limit.";
public static final String USER_DATA_MAP_KEY = "USER-LOGIN-DATA";
/** /**
* 构建app端用户token的缓存key * 构建app端用户token的缓存key
* *
......
package com.zq.common.config.security;/*
* Copyright 2019-2020 Zheng Jie
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjectUtil;
import com.zq.common.config.redis.RedisUtils;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.User;
import org.springframework.stereotype.Component;
import javax.crypto.spec.SecretKeySpec;
import javax.servlet.http.HttpServletRequest;
import javax.xml.bind.DatatypeConverter;
import java.security.Key;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
/**
* @author /
*/
@Slf4j
@Component
@RequiredArgsConstructor
public class TokenProvider implements InitializingBean {
private final RedisUtils redisUtils;
private final SecurityProperties properties;
public static final String AUTHORITIES_KEY = "auth";
private static Key key;
private static SignatureAlgorithm signatureAlgorithm;
@Override
public void afterPropertiesSet() {
signatureAlgorithm = SignatureAlgorithm.HS512;
byte[] keyBytes = DatatypeConverter.parseBase64Binary(properties.getBase64Secret());
key = new SecretKeySpec(keyBytes, signatureAlgorithm.getJcaName());
}
public static String createToken(Authentication authentication) {
String authorities = authentication.getAuthorities().stream()
.map(GrantedAuthority::getAuthority)
.collect(Collectors.joining(","));
return Jwts.builder()
.setSubject(authentication.getName())
.claim(AUTHORITIES_KEY, authorities)
.signWith(signatureAlgorithm, key)
// 加入ID确保生成的 Token 都不一致
.setId(IdUtil.simpleUUID())
.compact();
}
public Claims getClaims(String token) {
return Jwts.parser()
.setSigningKey(DatatypeConverter.parseBase64Binary(properties.getBase64Secret()))
.parseClaimsJws(token)
.getBody();
}
public Authentication getAuthentication(String token) {
Claims claims = getClaims(token);
// fix bug: 当前用户如果没有任何权限时,在输入用户名后,刷新验证码会抛IllegalArgumentException
Object authoritiesStr = claims.get(AUTHORITIES_KEY);
Collection<? extends GrantedAuthority> authorities =
ObjectUtil.isNotEmpty(authoritiesStr) ?
Arrays.stream(authoritiesStr.toString().split(","))
.map(SimpleGrantedAuthority::new)
.collect(Collectors.toList()) : Collections.emptyList();
User principal = new User(claims.getSubject(), "******", authorities);
return new UsernamePasswordAuthenticationToken(principal, token, authorities);
}
/**
* @param token 需要检查的token
*/
public void checkRenewal(String token) {
// 判断是否续期token,计算token的过期时间
long time = redisUtils.getExpire(properties.getOnlineKey() + token) * 1000;
Date expireDate = DateUtil.offset(new Date(), DateField.MILLISECOND, (int) time);
// 判断当前时间与过期时间的时间差
long differ = expireDate.getTime() - System.currentTimeMillis();
// 如果在续期检查的范围内,则续期
if (differ <= properties.getDetect()) {
long renew = time + properties.getRenew();
redisUtils.expire(properties.getOnlineKey() + token, renew, TimeUnit.MILLISECONDS);
}
}
public String getToken(HttpServletRequest request) {
String bearerToken = request.getHeader(properties.getHeader());
if (StringUtils.isBlank(bearerToken)) {
return null;
}
if (bearerToken.startsWith(properties.getTokenStartWith())) {
// 去掉令牌前缀
return bearerToken.replace(properties.getTokenStartWith(), "");
} else {
log.debug("非法Token:{}", bearerToken);
}
return null;
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment