|
@@ -15,11 +15,14 @@ import cn.com.qmth.examcloud.app.service.UserAuthService;
|
|
|
import org.apache.commons.lang3.StringUtils;
|
|
|
import org.slf4j.Logger;
|
|
|
import org.slf4j.LoggerFactory;
|
|
|
+import org.springframework.http.HttpStatus;
|
|
|
|
|
|
import javax.servlet.*;
|
|
|
import javax.servlet.FilterConfig;
|
|
|
import javax.servlet.http.HttpServletRequest;
|
|
|
+import javax.servlet.http.HttpServletResponse;
|
|
|
import java.io.IOException;
|
|
|
+import java.io.PrintWriter;
|
|
|
import java.util.Date;
|
|
|
|
|
|
import static cn.com.qmth.examcloud.app.model.Constants.PLATFORM_SESSION_EXPIRE_TIME;
|
|
@@ -47,7 +50,18 @@ public class TokenFilter implements Filter {
|
|
|
@Override
|
|
|
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
|
|
|
throws IOException, ServletException {
|
|
|
- CustomHttpServletRequest customRequest = this.initCustomRequest(servletRequest);
|
|
|
+ HttpServletRequest request = (HttpServletRequest) servletRequest;
|
|
|
+ HttpServletResponse response = (HttpServletResponse) servletResponse;
|
|
|
+
|
|
|
+ //移动端设备请求必须带“设备编号”参数
|
|
|
+ String deviceId = request.getHeader(Constants.PARAM_DEVICE_ID);
|
|
|
+ if (StringUtils.isBlank(deviceId)) {
|
|
|
+ Result result = new Result().error("[APP] deviceId must be not empty.");
|
|
|
+ this.render(response, result.toString());
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ CustomHttpServletRequest customRequest = this.initCustomRequest(request, deviceId);
|
|
|
if (customRequest != null) {
|
|
|
filterChain.doFilter(customRequest, servletResponse);
|
|
|
return;
|
|
@@ -55,9 +69,8 @@ public class TokenFilter implements Filter {
|
|
|
filterChain.doFilter(servletRequest, servletResponse);
|
|
|
}
|
|
|
|
|
|
- private CustomHttpServletRequest initCustomRequest(ServletRequest servletRequest) {
|
|
|
+ private CustomHttpServletRequest initCustomRequest(HttpServletRequest request, String deviceId) {
|
|
|
//用户带的token实际为缓存的redisKey
|
|
|
- HttpServletRequest request = (HttpServletRequest) servletRequest;
|
|
|
String redisKey = request.getHeader(Constants.PARAM_TOKEN);
|
|
|
if (StringUtils.isBlank(redisKey)) {
|
|
|
//token为空,则不用过滤处理
|
|
@@ -71,25 +84,23 @@ public class TokenFilter implements Filter {
|
|
|
return null;
|
|
|
}
|
|
|
|
|
|
- //处理登录过的信息
|
|
|
+ //处理已登录信息
|
|
|
CustomHttpServletRequest customRequest = new CustomHttpServletRequest(request);
|
|
|
if (!this.filterAccessUrl(request.getServletPath())) {
|
|
|
- //判断原始的login token是否在有效时间内
|
|
|
- if (loginInfo.hasExpired(PLATFORM_SESSION_EXPIRE_TIME)) {
|
|
|
- try {
|
|
|
- //已超过有效时间,则自动登录续期
|
|
|
- Result<UserInfo> result = userAuthService.login(loginInfo);
|
|
|
- UserInfo userInfo = result.getData();
|
|
|
- if (userInfo != null) {
|
|
|
- //登录成功后缓存新的login token
|
|
|
- log.info("redisKey:" + redisKey + " key:" + userInfo.getKey() + " newToken:" + userInfo.getToken());
|
|
|
- loginInfo.setToken(userInfo.getToken());
|
|
|
- loginInfo.setCreateTime(new Date());
|
|
|
- userAuthService.cacheLoginInfo(loginInfo, redisKey);
|
|
|
- }
|
|
|
- } catch (Exception e) {
|
|
|
- log.error(e.getMessage());
|
|
|
+ /* 同一个账号不同移动端设备,支持互踢 */
|
|
|
+ if (deviceId.equals(loginInfo.getDeviceId())) {
|
|
|
+ //设备编号相同
|
|
|
+ if (loginInfo.hasExpired(PLATFORM_SESSION_EXPIRE_TIME)) {
|
|
|
+ //判断原始的login token是否在有效时间内,若已超过有效时间,则自动登录续期
|
|
|
+ this.reLogin(loginInfo, redisKey);
|
|
|
}
|
|
|
+ } else {
|
|
|
+ //设备编号不同且Token在有效时间内,则互踢
|
|
|
+ if (!loginInfo.hasExpired(PLATFORM_SESSION_EXPIRE_TIME)) {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ loginInfo.setDeviceId(deviceId);
|
|
|
+ this.reLogin(loginInfo, redisKey);
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -101,6 +112,23 @@ public class TokenFilter implements Filter {
|
|
|
return customRequest;
|
|
|
}
|
|
|
|
|
|
+ private void reLogin(LoginInfo loginInfo, String redisKey) {
|
|
|
+ try {
|
|
|
+ Result<UserInfo> result = userAuthService.login(loginInfo);
|
|
|
+ UserInfo userInfo = result.getData();
|
|
|
+ if (userInfo == null) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ //登录成功后缓存新的Token信息
|
|
|
+ log.info(String.format("redisKey:%s key:%s newToken:%s", redisKey, userInfo.getKey(), userInfo.getToken()));
|
|
|
+ loginInfo.setToken(userInfo.getToken());
|
|
|
+ loginInfo.setCreateTime(new Date());
|
|
|
+ userAuthService.cacheLoginInfo(loginInfo, redisKey);
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error(e.getMessage());
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
private boolean filterAccessUrl(String url) {
|
|
|
//跳过不用处理的访问地址
|
|
|
if (url.contains("/user/logout")) {
|
|
@@ -109,6 +137,23 @@ public class TokenFilter implements Filter {
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
+ private void render(HttpServletResponse response, String json) {
|
|
|
+ PrintWriter out = null;
|
|
|
+ try {
|
|
|
+ response.setStatus(HttpStatus.OK.value());
|
|
|
+ response.setCharacterEncoding("UTF-8");
|
|
|
+ response.setContentType("application/json;charset=UTF-8");
|
|
|
+ out = response.getWriter();
|
|
|
+ out.print(json);
|
|
|
+ } catch (IOException e) {
|
|
|
+ log.error(e.getMessage(), e);
|
|
|
+ } finally {
|
|
|
+ if (out != null) {
|
|
|
+ out.close();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
public void setUserAuthService(UserAuthService userAuthService) {
|
|
|
this.userAuthService = userAuthService;
|
|
|
}
|