Commit e8cde8e0 by WeiCong

修复后台用户空

parent 541b9147
package org.sss.presentation.noui.jwt;
import java.io.PrintWriter;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.google.gson.Gson;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
......@@ -20,133 +14,137 @@ import org.sss.presentation.noui.util.NumericUtil;
import org.sss.presentation.noui.util.RedisUtil;
import org.sss.presentation.noui.util.StringUtil;
import com.google.gson.Gson;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.PrintWriter;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
public class TokenInterceptor implements HandlerInterceptor {
private static Map<String, Integer> CounterMap = new ConcurrentHashMap<>(); //计数map
@Autowired
private NoUiVersion noUiVersion;
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception arg3) throws Exception {
addCount(NoUiUtils.getToken(),-1); //计算器减1
NoUiUtils.clearLoginInfo();
}
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView model) throws Exception {
}
// 拦截每个请求
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
response.setCharacterEncoding("utf-8");
NoUiRequest noUiRequest = new NoUiRequest(request, "", null);
String token = noUiRequest.getToken();
String userId = noUiRequest.getUserId();
String terminalType = noUiRequest.getTerminalType(); // APP WEB
// token不存在
if (StringUtil.isEmpty(token)) {
Result rt = new Result(ErrorCodes.LOGIN_TOKEN_ISNULL, "登录token不能为空", null, noUiVersion.getVersion());
responseMessage(response, response.getWriter(), rt);
return false;
}
// userId不存在
if (StringUtil.isEmpty(userId)) {
Result rt = new Result(ErrorCodes.LOGIN_ID_ISNULL, "用户id不能为空", null, noUiVersion.getVersion());
responseMessage(response, response.getWriter(), rt);
return false;
}
//如果为后台直接调用交易,则直接跳过token验证,无需redis缓存
if (token.startsWith(Constants.BACKGROUND_FLAG)) {
return true;
}
JwtLogin login = JWT.unsign(token, JwtLogin.class);
if (login == null || (!userId.equals((login.getUserId())))) {
Result rt = new Result(ErrorCodes.LOGIN_TOKEN_CHECKERROR, "用户token或ID验证不通过", null, noUiVersion.getVersion());
responseMessage(response, response.getWriter(), rt);
return false;
}
RedisLoginInfo redisLoginInfo = (RedisLoginInfo) RedisUtil.get(StringUtil.userUniqueId(noUiRequest));
if (redisLoginInfo == null) {
Result rt = new Result(ErrorCodes.LOGIN_ERROR, "登陆异常", null, noUiVersion.getVersion());
responseMessage(response, response.getWriter(), rt);
return false;
}
//验证token是否一致
if(!token.equals(redisLoginInfo.getToken())){
Result rt = new Result(ErrorCodes.LOGIN_TOKEN_CHECKERROR, "token失效,该用户被强迫下线", null, noUiVersion.getVersion());
responseMessage(response, response.getWriter(), rt);
return false;
}
// 验证登录时间
if (System.currentTimeMillis() > redisLoginInfo.getExpiredTime()) {
Result rt = new Result(ErrorCodes.LOGIN_TIMEOUT, "会话超时,请重新登录。超时时间戳:"+redisLoginInfo.getExpiredTime()+
",当前时间戳:"+System.currentTimeMillis(), null, noUiVersion.getVersion());
responseMessage(response, response.getWriter(), rt);
return false;
}
//超过最大并发数限制
if(compareAndSet(noUiRequest.getToken(),1,noUiVersion.getCurr_max_num()) < 0)
{
Result rt = new Result(ErrorCodes.GT_MAX_CURR_NUM, "超过单个会话并发数", null, noUiVersion.getVersion());
responseMessage(response, response.getWriter(), rt);
return false;
}
// 重新刷入登陆时间
RedisLoginInfo nweRedisLoginInfo = new RedisLoginInfo(userId, token, NumericUtil.sessionTimeOut(), redisLoginInfo.getSysmod(),noUiRequest.getTerminalType());
RedisUtil.set(Constants.SESSION + "." + userId + "." + terminalType, nweRedisLoginInfo);
NoUiUtils.setLoginInfo(nweRedisLoginInfo);
return true;
}
// 请求不通过,返回错误信息给客户端
private void responseMessage(HttpServletResponse response, PrintWriter out, Result result) {
response.setContentType("application/json; charset=utf-8");
String json = new Gson().toJson(result);
out.print(json);
out.flush();
out.close();
}
public static int compareAndSet(String token,int cnt,int max_curr_cnt)
{
synchronized (CounterMap) {
int count = getCount(token);
if(count >= max_curr_cnt)
return -1;
count += cnt;
if(count <= 0)
CounterMap.remove(token);
else
CounterMap.put(token,count);
return count;
}
}
public static int addCount(String token,int cnt)
{
synchronized (CounterMap) {
int count = getCount(token);
count += cnt;
if(count <= 0)
CounterMap.remove(token);
else
CounterMap.put(token,count);
return count;
}
}
public static int getCount(String token)
{
Integer count = CounterMap.get(token);
if(count == null)
return 0;
return count;
}
private static Map<String, Integer> CounterMap = new ConcurrentHashMap<>(); //计数map
@Autowired
private NoUiVersion noUiVersion;
public static int compareAndSet(String token, int cnt, int max_curr_cnt) {
synchronized (CounterMap) {
int count = getCount(token);
if (count >= max_curr_cnt)
return -1;
count += cnt;
if (count <= 0)
CounterMap.remove(token);
else
CounterMap.put(token, count);
return count;
}
}
public static int addCount(String token, int cnt) {
synchronized (CounterMap) {
int count = getCount(token);
count += cnt;
if (count <= 0)
CounterMap.remove(token);
else
CounterMap.put(token, count);
return count;
}
}
public static int getCount(String token) {
Integer count = CounterMap.get(token);
if (count == null)
return 0;
return count;
}
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception arg3) throws Exception {
String token = request.getHeader("token");
if (!StringUtil.isEmpty(token) && !token.startsWith(Constants.BACKGROUND_FLAG)){
addCount(token, -1); //计算器减1
}
NoUiUtils.clearLoginInfo();
}
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView model) throws Exception {
}
// 拦截每个请求
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
response.setCharacterEncoding("utf-8");
NoUiRequest noUiRequest = new NoUiRequest(request, "", null);
String token = noUiRequest.getToken();
String userId = noUiRequest.getUserId();
String terminalType = noUiRequest.getTerminalType(); // APP WEB
// token不存在
if (StringUtil.isEmpty(token)) {
Result rt = new Result(ErrorCodes.LOGIN_TOKEN_ISNULL, "登录token不能为空", null, noUiVersion.getVersion());
responseMessage(response, response.getWriter(), rt);
return false;
}
// userId不存在
if (StringUtil.isEmpty(userId)) {
Result rt = new Result(ErrorCodes.LOGIN_ID_ISNULL, "用户id不能为空", null, noUiVersion.getVersion());
responseMessage(response, response.getWriter(), rt);
return false;
}
//如果为后台直接调用交易,则直接跳过token验证,无需redis缓存
if (token.startsWith(Constants.BACKGROUND_FLAG)) {
return true;
}
JwtLogin login = JWT.unsign(token, JwtLogin.class);
if (login == null || (!userId.equals((login.getUserId())))) {
Result rt = new Result(ErrorCodes.LOGIN_TOKEN_CHECKERROR, "用户token或ID验证不通过", null, noUiVersion.getVersion());
responseMessage(response, response.getWriter(), rt);
return false;
}
RedisLoginInfo redisLoginInfo = (RedisLoginInfo) RedisUtil.get(StringUtil.userUniqueId(noUiRequest));
if (redisLoginInfo == null) {
Result rt = new Result(ErrorCodes.LOGIN_ERROR, "登陆异常", null, noUiVersion.getVersion());
responseMessage(response, response.getWriter(), rt);
return false;
}
//验证token是否一致
if (!token.equals(redisLoginInfo.getToken())) {
Result rt = new Result(ErrorCodes.LOGIN_TOKEN_CHECKERROR, "token失效,该用户被强迫下线", null, noUiVersion.getVersion());
responseMessage(response, response.getWriter(), rt);
return false;
}
// 验证登录时间
if (System.currentTimeMillis() > redisLoginInfo.getExpiredTime()) {
Result rt = new Result(ErrorCodes.LOGIN_TIMEOUT, "会话超时,请重新登录。超时时间戳:" + redisLoginInfo.getExpiredTime() +
",当前时间戳:" + System.currentTimeMillis(), null, noUiVersion.getVersion());
responseMessage(response, response.getWriter(), rt);
return false;
}
//超过最大并发数限制
if (compareAndSet(noUiRequest.getToken(), 1, noUiVersion.getCurr_max_num()) < 0) {
Result rt = new Result(ErrorCodes.GT_MAX_CURR_NUM, "超过单个会话并发数", null, noUiVersion.getVersion());
responseMessage(response, response.getWriter(), rt);
return false;
}
// 重新刷入登陆时间
RedisLoginInfo nweRedisLoginInfo = new RedisLoginInfo(userId, token, NumericUtil.sessionTimeOut(), redisLoginInfo.getSysmod(), noUiRequest.getTerminalType());
RedisUtil.set(Constants.SESSION + "." + userId + "." + terminalType, nweRedisLoginInfo);
NoUiUtils.setLoginInfo(nweRedisLoginInfo);
return true;
}
// 请求不通过,返回错误信息给客户端
private void responseMessage(HttpServletResponse response, PrintWriter out, Result result) {
response.setContentType("application/json; charset=utf-8");
String json = new Gson().toJson(result);
out.print(json);
out.flush();
out.close();
}
}
\ No newline at end of file
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