Commit e8cde8e0 by WeiCong

修复后台用户空

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