#账号登录
单点登录(Single Sign On),简称为 SSO。单点登录是登录之后所有该域名的网站都可以不用登录了包括子域名。用户的一次登录能得到其他所有系统的信任。
1、将账号信息放入缓存
2、PC端系统可以共用一个token/Cookie,但是若有小程序等不同设备登录,则会需要不同的token
3、登录使用拦截器org.springframework.web.servlet.HandlerInterceptor
补充:
1、如果楼主说的一机一号的机制,那么可以直接绑定用户首次登录的IP地址,将用户的IP地址绑定在数据库中,每次登录的时候判断IP是否正确。如用户是IP是自动获取的话,那么就绑定用户的硬件串口号。
登录拦截器
package yunnex.vip.interceptor;
import java.time.LocalDateTime;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import yunnex.common.config.anotation.LoginPermission;
import yunnex.common.exception.ErrorCodes;
import yunnex.common.trace.logger.TraceLoggerFactory;
import yunnex.common.utils.StringUtilsExt;
import yunnex.common.utils.UserAgentUtil;
import yunnex.pinka.dto.ApiResult;
import yunnex.vip.constants.BossConstant;
import yunnex.vip.dto.shop.VipShopAccountDto;
import yunnex.vip.service.shop.VipShopAccountService;
/**
* 业务描述:登陆拦截器 区分 PC端还是移动端
*
* @author WilliamZhu
* @version 1.0
* @date 2018/10/18 0018
*/
public class LoginInterceptor implements HandlerInterceptor {
private static final Logger logger = TraceLoggerFactory.getTraceLogger(LoginInterceptor.class);
@Autowired
private RedisTemplate<String, String> redisTemplate;
@Autowired
private VipShopAccountService vipShopAccountService;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
ApiResult apiResult = ApiResult.build(false);
// 验证权限
if (this.isLogin(request, handler, apiResult)) {
return true;
}
response.getWriter().write(apiResult.toString());
return false;
}
/**
* 描述 判断商户是否已经登陆
*
* @param request
* @param handler
* @author: WilliamZhu
* @Time: 15:26 2018/10/18 0018
*/
private boolean isLogin(HttpServletRequest request, Object handler, ApiResult apiResult) {
if (handler instanceof HandlerMethod) {
HandlerMethod handlerMethod = (HandlerMethod) handler;
// 获取方法上的注解
LoginPermission loginPermission = handlerMethod.getMethod().getAnnotation(LoginPermission.class);
// 如果方法上的注解为空 则获取类的注解
if (loginPermission == null) {
loginPermission = handlerMethod.getMethod().getDeclaringClass().getAnnotation(LoginPermission.class);
}
// 如果标记了注解,则判断权限
if (loginPermission != null) {
String token = request.getHeader("token");
String ua = request.getHeader(UserAgentUtil.USER_AGENT);
logger.info("ua={}", ua);
if (StringUtilsExt.isBlank(token)) {
apiResult.error("token is null");
return false;
} else {
if (UserAgentUtil.isMobileAgent(ua)) {//移动端
if (!hasKey(BossConstant.LOGIN_SHOP_KEY + token)) {
//进一步查看数据库中是否存在
VipShopAccountDto accountByToken = vipShopAccountService.getAccountByToken(token);
if (null != accountByToken) {
if (LocalDateTime.now().isBefore(accountByToken.getExpireTime())) {//当前时间比过期早
return true;
}
}
apiResult.setCode(ErrorCodes.EXPIRE_TOKEN_INVALID);
return false;
}
} else {//PC端
if (!hasKey(BossConstant.LOGIN_SHOP_PC_KEY + token)) {
//进一步查看数据库中是否存在
VipShopAccountDto accountByToken = vipShopAccountService.getAccountByPCToken(token);
if (null != accountByToken) {
if (LocalDateTime.now().isBefore(accountByToken.getExpireTime())) {//当前时间比过期早
return true;
}
}
apiResult.setCode(ErrorCodes.EXPIRE_TOKEN_INVALID);
return false;
}
}
} return true;
} return true;
} return true;
}
private boolean hasKey(String tokenKey) {
try {
return redisTemplate.hasKey(tokenKey);
} catch (Exception e) {
return false;
}
}
}