java cookie 单点登录和登录拦截器 从实现到原理

1、准备两张表,一张user一张ticket表(ticket用户登录后存储票据)

生成表语句

DROP TABLE IF EXISTS `per_users`;
CREATE TABLE `per_users` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '用户id',
  `user_code` varchar(20) NOT NULL COMMENT '用户名',
  `user_pd` varchar(100) NOT NULL COMMENT '登录密码',
  `salt` varchar(64) NOT NULL COMMENT '盐',
  `user_status` int(11) NOT NULL COMMENT '用户状态(0可用 1禁用)',
  `is_admin` char(1) NOT NULL DEFAULT 'n' COMMENT '是否管理员',
  `is_delete` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否删除,0-未删除,1-删除',
  `create_user` varchar(20) NOT NULL COMMENT '创建人',
  `update_user` varchar(20) DEFAULT NULL COMMENT '更新人',
  `create_time` datetime NOT NULL COMMENT '创建时间',
  `update_time` datetime NOT NULL COMMENT '更新时间',
  `ts` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '时间戳',
  PRIMARY KEY (`id`),
  UNIQUE KEY `user_user_code` (`user_code`)
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8 COMMENT='用户信息表';
DROP TABLE IF EXISTS `login_ticket`;
CREATE TABLE `login_ticket` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '用户id',
  `user_code` varchar(20) NOT NULL COMMENT '用户名',
  `ticket` varchar(64) NOT NULL COMMENT '盐',
  `expire_time` datetime NOT NULL COMMENT '失效时间',
  `is_delete` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否删除,0-未删除,1-删除',
  `create_user` varchar(20) NOT NULL COMMENT '创建人',
  `update_user` varchar(20) DEFAULT NULL COMMENT '更新人',
  `create_time` datetime NOT NULL COMMENT '创建时间',
  `update_time` datetime NOT NULL COMMENT '更新时间',
  `ts` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '时间戳',
  PRIMARY KEY (`id`),
  UNIQUE KEY `AK_Key_1` (`ticket`)
) ENGINE=InnoDB AUTO_INCREMENT=22 DEFAULT CHARSET=utf8 COMMENT='登录票据';

2、准备一个 CookieUtils类

package com.jd.jdx.x.sr.aps.ui.common;

import com.jd.bk.common.util.string.StringUtils;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * cookie工具类
 * User: wanghonghong5
 * DateTime: 2020/2/14 17:01
 * Version:1.0.0.0
 */
public class CookieUtils {

    public static String getCookieValue(HttpServletRequest request, String name) {
        Cookie[] cookies = request.getCookies();
        if (null != cookies && cookies.length > 0) {
            for (Cookie c : cookies) {
                if (StringUtils.equals(c.getName(), name)) {
                    return c.getValue();
                }
            }
        }
        return null;
    }

    public static int getCookieMaxAge(HttpServletRequest request, String name) {
        Cookie[] cookies = request.getCookies();
        if (null != cookies && cookies.length > 0) {
            for (Cookie c : cookies) {
                if (StringUtils.equals(c.getName(), name)) {
                    return c.getMaxAge();
                }
            }
        }
        return -1;
    }

    public static void deleteCookie(HttpServletRequest request, HttpServletResponse response, String name) {
        Cookie[] cookies = request.getCookies();
        if (null != cookies && cookies.length > 0) {
            for (Cookie c : cookies) {
                if (StringUtils.equals(c.getName(), name)) {
                    c.setValue("");
                    c.setMaxAge(0);
                    response.addCookie(c);
                    break;
                }
            }
        }
    }

    public static void deleteAllCookies(HttpServletRequest request, HttpServletResponse response) {
        Cookie[] cookies = request.getCookies();
        if (null != cookies && cookies.length > 0) {
            for (Cookie c : cookies) {
                c.setValue("");
                c.setMaxAge(0);
                response.addCookie(c);
            }
        }
    }

    public static void addCookie(HttpServletResponse response, String name, String value, String path, int maxAge, String domain) {
        Cookie cookie = new Cookie(name, value);
        cookie.setPath(path);
        if(StringUtils.validateStringNotNull(domain)){
            cookie.setDomain(domain);
        }
        if (maxAge > 0) {
            cookie.setMaxAge(maxAge);
        }
        response.addCookie(cookie);
    }

    public static void deleteAllCookies(HttpServletRequest request, HttpServletResponse response, String path, String domain) {
        Cookie[] cookies = request.getCookies();
        if (null != cookies && cookies.length > 0) {
            for (Cookie c : cookies) {
                c.setValue("");
                c.setMaxAge(0);
                c.setPath(path);
                c.setDomain(domain);
                response.addCookie(c);
            }
        }
    }
}

3、设置登录方法

@RequestMapping(value = "doLogin.do", method = RequestMethod.POST)
    public @ResponseBody
    Result doLogin(HttpServletResponse response, HttpServletRequest request, LoginParam loginParam) {
        Result result = loginBusiness.login(loginParam);
        if (result.isSuccess()) {
            String token = (String) result.get(BaseConstants.SERVICE_RETURN_OBJ_DEFAULT_KEY);
            CookieUtils.addCookie(response, CookieConstants.COOKIE_TOKEN, token, path, maxAge, domain);
            Result tmp = new Result();
            tmp.setSuccess(true);
            tmp.setResultCode(result.getResultCode());
            return tmp;
        } else {
            return result;
        }
    }

domain设置为二级域名,这样凡是在二级域名下登录过的都会记录到ticket那张表里。

单点登录原理:erp cms wcs等系统,所有需要登录的地方需要走erp的登录地址,此时erp将生成的ticket票据插入到ticket表中,这样无论从哪个系统登录都会带着票据ticket过来

具体请求如下:

每次请求request中都会带cookies信息

后台代码可以获取token  先校验token是否在缓存中,如果在缓存中这个token校验通过,如果token不在缓存中调erp校验token,如果通过则把token存入缓存中。

package com.jd.jdx.x.sr.cms.ui.interceptor;

import com.jd.bk.common.util.json.JsonUtil;
import com.jd.bk.common.util.string.StringUtils;
import com.jd.bk.common.web.result.Result;
import com.jd.jdx.x.sr.cms.business.user.LoginBusiness;
import com.jd.jdx.x.sr.cms.domain.base.constants.BaseConstants;
import com.jd.jdx.x.sr.cms.domain.stk.constants.StkConstants;
import com.jd.jdx.x.sr.cms.domain.user.dto.*;
import com.jd.jdx.x.sr.cms.domain.util.CommonConfig;
import com.jd.jdx.x.sr.cms.ui.common.CookieUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;

/**
 * 登录拦截器
 * User: liangendi
 * DateTime: 2020/2/19 9:16
 * Version:1.0.0.0
 */
public class LoginInterceptor extends BaseInterceptor implements HandlerInterceptor {
    private final static Logger logger = LogManager.getLogger(LoginInterceptor.class);

    @Value("${page.intercetpor.prefix}")
    private String prefix;
    @Value("${page.cookies.domain.name}")
    private String domain;
    @Value("${page.cookies.path}")
    private String path;
    @Value("${page.cookies.maxAge}")
    private Integer maxAge;

    /**
     * 登录处理类
     */
    private LoginBusiness loginBusiness;

    @Override
    public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
        try {
            //1.登录开关关闭,不拦截登录
            if(!CommonConfig.LOGIN_SWITCH){
                return true;
            }
            //2.判断请求是否需要登录拦截
            if (isExclude(httpServletRequest)) {
                return true;
            }
            //3.检测Cookie中是否含有token,存在验证token的合法性,不存在则跳转到登录
            String token = CookieUtils.getCookieValue(httpServletRequest, CommonConfig.COOKIE_TOKEN);
            if (StringUtils.isEmpty(token)) {
                return this.toLoginPage(httpServletRequest, httpServletResponse);
            }
            //4.先取缓存,如果校验token缓存失败,则调erp验证token
            String userCode = httpServletRequest.getParameter(CommonConfig.USER_CODE);
            if(StringUtils.isNotEmpty(userCode)){
                UserCacheInfo info = UserCache.INSTANCE.getUserCache(userCode);
                if(info!=null){
                    String cacheToken = info.getToken();
                    if(token.equals(cacheToken)){
                        //缓存token校验通过
                        httpServletRequest.setAttribute(CommonConfig.USER_CODE, userCode);
                        //cookie赋值
                        CookieUtils.addCookie(httpServletResponse, CommonConfig.COOKIE_TOKEN, token, path, maxAge, domain);
                        return true;
                    }
                }
            }
            //5.校验缓存token失败,则调ERP校验token
            TicketParam ticketParam = new TicketParam();
            ticketParam.setTicket(token);
            Result result = loginBusiness.verifyToken(ticketParam);
            if (result.isSuccess()) {
                PerUsersDto perUsersDto = JsonUtil.fromJson((String)result.get(BaseConstants.SERVICE_RETURN_OBJ_DEFAULT_KEY), PerUsersDto.class);
                if (perUsersDto != null) {
                    //更新缓存token
                    userCode = perUsersDto.getUserCode();
                    if(StringUtils.isNotEmpty(userCode)){
                        UserCacheInfo info = UserCache.INSTANCE.getUserCache(userCode);
                        if(info == null){
                            info = new UserCacheInfo();
                        }
                        info.setToken(token);
                        UserCache.INSTANCE.addUserCache(userCode, info);
                    }
                    //token校验通过
                    httpServletRequest.setAttribute(CommonConfig.USER_CODE, userCode);
                    //cookie赋值
                    CookieUtils.addCookie(httpServletResponse, CommonConfig.COOKIE_TOKEN, token, path, maxAge, domain);
                    return true;
                }
            }

            return this.toLoginPage(httpServletRequest, httpServletResponse);

        } catch (Exception e) {
            logger.error("LoginInterceptor error:",e);
            return this.toLoginPage(httpServletRequest, httpServletResponse);
        }
    }

    @Override
    public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {

    }

    @Override
    public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {

    }

    public boolean toLoginPage(HttpServletRequest request, HttpServletResponse response) throws IOException {
        if ("XMLHttpRequest".equalsIgnoreCase(request.getHeader("X-Requested-With"))) {
            response.setStatus(401);
            response.setHeader("Location", prefix+"/login");
        } else {
            response.sendRedirect(prefix+"/login");
        }
        return false;
    }

    public void setLoginBusiness(LoginBusiness loginBusiness) {
        this.loginBusiness = loginBusiness;
    }
}

如果是erp自己系统,则只需要去数据库里查询token是否存在即可。

 添加登录拦截器

public class LoginInterceptor extends BaseInterceptor implements HandlerInterceptor {
    private final static Logger logger = LogManager.getLogger(LoginInterceptor.class);

    /**
     * 登录处理类
     */
    private LoginBusiness loginBusiness;



    @Override
    public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
        try {
            logger.error("uri===="+httpServletRequest.getRequestURI());
            //1.判断请求是否需要登录拦截
            if (isExclude(httpServletRequest)) {
                return true;
            }
            String token = CookieUtils.getCookieValue(httpServletRequest, CookieConstants.COOKIE_TOKEN);
            //2.检测Cookie中是否含有token,存在验证token的合法性,不存在则跳转到登录
            if (StringUtils.validateStringNotNull(token)) {
                TicketParam ticketParam = new TicketParam();
                ticketParam.setTicket(token);
                Result result = loginBusiness.verifyTicket(ticketParam);
                if (result.isSuccess()) {
                    PerUsersDto perUsersDto = (PerUsersDto) result.get(BaseConstants.SERVICE_RETURN_OBJ_DEFAULT_KEY);
                    if (perUsersDto != null) {
                        httpServletRequest.setAttribute("user", perUsersDto);
                        return true;
                    } else {

                        return this.toLoginPage(httpServletRequest, httpServletResponse);
                    }
                } else {
                    return this.toLoginPage(httpServletRequest, httpServletResponse);
                }
            } else {
                return this.toLoginPage(httpServletRequest, httpServletResponse);
            }
        } catch (Exception e) {
            logger.error("LoginInterceptor error:",e);
            return this.toLoginPage(httpServletRequest, httpServletResponse);
        }

    }

    @Override
    public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {

    }

    @Override
    public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {

    }

    public boolean toLoginPage(HttpServletRequest request, HttpServletResponse response) throws IOException {
        StringBuilder loginUrl = new StringBuilder(getPrefixUrl());
        loginUrl.append("/user/login");
        if ("XMLHttpRequest".equalsIgnoreCase(request.getHeader("X-Requested-With"))) {
            response.setStatus(401);
            response.setHeader("Location", loginUrl.toString());
        } else {
            response.sendRedirect(loginUrl.toString());
        }
        return false;
    }

    public void setLoginBusiness(LoginBusiness loginBusiness) {
        this.loginBusiness = loginBusiness;
    }


}
public class BaseInterceptor {
    /**
     * 不需要拦截的路径集合
     */
    private List<String> excludePaths;

    /**
     * 请求的前缀
     */
    private String prefixUrl;
    /**
     * 拦截url的前缀
     */
    private String interceptorPrefix;

    public boolean isExclude(HttpServletRequest request) {
        return this.isExclude(request.getRequestURI(), excludePaths);
    }

    public boolean isExclude(String uri, List<String> excludes) {
        if (CollectionUtils.isNotEmpty(excludes)) {
            for (String excludePath : excludes) {
                if (excludePath.endsWith("/**")) {
                    if (uri.startsWith(excludePath.substring(0, excludePath.length() - 3))) {
                        return true;
                    }
                } else if (uri.equals(excludePath)) {
                    return true;
                }
            }
        }
        return false;
    }

    public void setExcludePaths(List<String> excludePaths) {
        this.excludePaths = excludePaths;
    }

    public String getPrefixUrl() {
        return prefixUrl;
    }

    public void setPrefixUrl(String prefixUrl) {
        this.prefixUrl = prefixUrl;
    }

    public String getInterceptorPrefix() {
        return interceptorPrefix;
    }

    public void setInterceptorPrefix(String interceptorPrefix) {
        this.interceptorPrefix = interceptorPrefix;
    }
}
public interface LoginBusiness {
    /**
     * 登录
     * @return 返回结果中携带登录票据tiket
     */
    public Result login(LoginParam loginParam);

    /**
     * 单点登录
     * @param taskToken
     * @return 返回结果中携带登录票据tiket
     */
    public Result ssoLogin(TaskToken taskToken);

    /**
     * 验证ticket
     * @param ticketParam
     * @return
     */
    public Result verifyTicket(TicketParam ticketParam);

    /**
     * 单点登录退出
     * @param ticketParam
     * @return
     */
    public Result loginOut(TicketParam ticketParam);

}
public class LoginBusinessImpl implements LoginBusiness {
    private final static Logger logger = LogManager.getLogger(LoginBusinessImpl.class);

    private LoginService loginService;

    @Override
    public Result login(LoginParam loginParam) {
        Result result = new Result();
        try {
            result = validateLoginParam(loginParam);
            if(result.isSuccess()){
                result = loginService.login(loginParam, false);
            }
            return result;
        } catch (Exception ex) {
            logger.error("LoginBusinessImpl!user() -> error!! 登录{}", ex);
            result.setSuccess(false);
            result.setResultCode(LoginConstants.SERVICE_RETURN_FALSE_CODE);
            result.addDefaultModel(BaseConstants.SERVICE_RETURN_MESSAGE_DEFAULT_KEY, LoginConstants.SERVICE_RETURN_FALSE_MESSAGE);
        }
        return result;
    }

    @Override
    public Result ssoLogin(TaskToken taskToken) {
        Result result = new Result();
        try {
            LoginParam loginParam = JsonUtil.fromJson(taskToken.getTaskJson(),LoginParam.class);
            if(!StringUtils.validateStringNotNull(taskToken.getCallCode())){
                result.setSuccess(false);
                result.setResultCode(LoginConstants.WS_PARAM_SYS_CODE_NULL_CODE);
                result.addDefaultModel(BaseConstants.SERVICE_RETURN_MESSAGE_DEFAULT_KEY, LoginConstants.WS_PARAM_SYS_CODE_NULL_MESSAGE);
                return result;
            }
            loginParam.setSysCode(taskToken.getCallCode());
            result = validateLoginParam(loginParam);
            if(result.isSuccess()){
                result = loginService.login(loginParam, true);
            }
            return result;
        } catch (Exception ex) {
            logger.error("LoginBusinessImpl!ssoLogin() -> error!! 登录{}", ex);
            result.setSuccess(false);
            result.setResultCode(LoginConstants.SERVICE_RETURN_FALSE_CODE);
            result.addDefaultModel(BaseConstants.SERVICE_RETURN_MESSAGE_DEFAULT_KEY, LoginConstants.SERVICE_RETURN_FALSE_MESSAGE);
        }
        return result;
    }

    @Override
    public Result verifyTicket(TicketParam ticketParam) {
        Result result = new Result();
        try {
            result = validateTicketParam(ticketParam);
            result = loginService.verifyTicket(ticketParam);
            return result;
        } catch (Exception ex) {
            logger.error("LoginBusinessImpl!verifyTicket() -> error!! 验证ticket{}", ex);
            result.setSuccess(false);
            result.setResultCode(LoginConstants.SERVICE_RETURN_FALSE_CODE);
            result.addDefaultModel(BaseConstants.SERVICE_RETURN_MESSAGE_DEFAULT_KEY, LoginConstants.SERVICE_RETURN_FALSE_MESSAGE);
        }
        return result;
    }

    @Override
    public Result loginOut(TicketParam ticketParam) {
        Result result = new Result();
        try {
            result = validateTicketParam(ticketParam);
            result = loginService.loginOut(ticketParam);
            return result;
        } catch (Exception ex) {
            logger.error("LoginBusinessImpl!verifyTicket() -> error!! 退出{}", ex);
            result.setSuccess(false);
            result.setResultCode(LoginConstants.SERVICE_RETURN_FALSE_CODE);
            result.addDefaultModel(BaseConstants.SERVICE_RETURN_MESSAGE_DEFAULT_KEY, LoginConstants.SERVICE_RETURN_FALSE_MESSAGE);
        }
        return result;
    }

    /**
     * 校验添加商品参数
     *
     * @param loginParam
     * @return
     */
    private Result validateLoginParam(LoginParam loginParam) {
        Result result = new Result();
        result.setSuccess(true);
        if (loginParam == null) {
            result.setSuccess(false);
            result.setResultCode(LoginConstants.WS_PARAM_OBJ_NULL_CODE);
            result.addDefaultModel(BaseConstants.SERVICE_RETURN_MESSAGE_DEFAULT_KEY, LoginConstants.WS_PARAM_OBJ_NULL_MESSAGE);
            return result;
        }
        if (!StringUtils.validateStringNotNull(loginParam.getUserCode())) {
            result.setSuccess(false);
            result.setResultCode(LoginConstants.WS_PARAM_USER_CODE_NULL_CODE);
            result.addDefaultModel(BaseConstants.SERVICE_RETURN_MESSAGE_DEFAULT_KEY, LoginConstants.WS_PARAM_USER_CODE_NULL_MESSAGE);
            return result;
        }
        if (!StringUtils.validateStringNotNull(loginParam.getUserPd())) {
            result.setSuccess(false);
            result.setResultCode(LoginConstants.WS_PARAM_USER_PD_NULL_CODE);
            result.addDefaultModel(BaseConstants.SERVICE_RETURN_MESSAGE_DEFAULT_KEY, LoginConstants.WS_PARAM_USER_PD_NULL_MESSAGE);
            return result;
        }
        return result;
    }
    /**
     * 校验添加商品参数
     *
     * @param ticketParam
     * @return
     */
    private Result validateTicketParam(TicketParam ticketParam) {
        Result result = new Result();
        result.setSuccess(true);
        if (ticketParam == null) {
            result.setSuccess(false);
            result.setResultCode(LoginConstants.WS_PARAM_OBJ_NULL_CODE);
            result.addDefaultModel(BaseConstants.SERVICE_RETURN_MESSAGE_DEFAULT_KEY, LoginConstants.WS_PARAM_OBJ_NULL_MESSAGE);
            return result;
        }
        if (!StringUtils.validateStringNotNull(ticketParam.getTicket())) {
            result.setSuccess(false);
            result.setResultCode(LoginConstants.WS_PARAM_TICKET_NULL_CODE);
            result.addDefaultModel(BaseConstants.SERVICE_RETURN_MESSAGE_DEFAULT_KEY, LoginConstants.WS_PARAM_TICKET_NULL_MESSAGE);
            return result;
        }
        return result;
    }


    public void setLoginService(LoginService loginService) {
        this.loginService = loginService;
    }
}
public interface LoginService {
    /**
     * 登录
     * @param loginParam
     * @return
     */
    public Result login(LoginParam loginParam, boolean pdDecrpty);
    /**
     * 验证ticket
     * @param ticketParam
     * @return
     */
    public Result verifyTicket(TicketParam ticketParam);

    /**
     * 退出
     * @param ticketParam
     * @return
     */
    public Result loginOut(TicketParam ticketParam);
}
public class LoginServiceImpl implements LoginService {
    private static final Logger logger = Logger.getLogger(LoginServiceImpl.class);
    /**
     * 业务模块-用户Manager接口
     */
    private PerUsersManager perUsersManager;
    /**
     * 业务模块- 登录票据Manager接口
     */
    private LoginTicketManager loginTicketManager;
    /**
     * 业务模块 - 系统接口
     */
    private PerSysManager perSysManager;
    /**
     * 默认失效时间是1个月,单位是秒
     */
    private Long expireTime = 30 * 24 * 3600l;

    @Override
    public Result login(LoginParam loginParam, boolean pdDecrpty) {
        Result result = new Result();
        try {
            //验证参数是否为空,为空返回自定义错误信息(Code 、 Message)
            if (null == loginParam
                    || !StringUtils.validateStringNotNull(loginParam.getUserCode())
                    || !StringUtils.validateStringNotNull(loginParam.getUserPd())
            ) {
                result.setSuccess(false);
                result.setResultCode(LoginConstants.WS_PARAM_OBJ_NULL_CODE);
                result.addDefaultModel(BaseConstants.SERVICE_RETURN_MESSAGE_DEFAULT_KEY, LoginConstants.WS_PARAM_OBJ_NULL_MESSAGE);
                return result;
            }

            PerUsers perUsers = perUsersManager.getUserPd(loginParam.getUserCode());
            if (perUsers != null) {
                if (perUsers.getUserStatus() == null || perUsers.getUserStatus() == 1) {
                    result.setSuccess(false);
                    result.setResultCode(LoginConstants.WS_PARAM_USER_STATUS_ERROR_CODE);
                    result.addDefaultModel(BaseConstants.SERVICE_RETURN_MESSAGE_DEFAULT_KEY, LoginConstants.WS_PARAM_USER_STATUS_ERROR_MESSAGE);
                    return result;
                }
                String userPd = loginParam.getUserPd();
                // 把明文密码+随机盐加密和数据库里取到的密码进行比较,如果相同登录成功
                String successPwd = UserPdEncryptUtils.encryPd(userPd, perUsers.getSalt());
                //登录成功,返回
                if (successPwd.equals(perUsers.getUserPd())) {
                    LoginTicket loginTicket = new LoginTicket();
                    long nowTime = System.currentTimeMillis();
                    long expire = nowTime + expireTime * 1000;
                    loginTicket.setExpireTime(new Date(expire));
                    loginTicket.setUserCode(perUsers.getUserCode());
                    loginTicket.setCreateUser(perUsers.getUserCode());
                    loginTicket.setUpdateUser(perUsers.getUserCode());
                    loginTicket.setTicket(createTicket());
                    loginTicketManager.insertLoginTicket(loginTicket);
                    result.setSuccess(true);
                    result.setResultCode(BaseConstants.SERVICE_RESULT_SUCCESS_CODE);
                    result.addDefaultModel(BaseConstants.SERVICE_RETURN_OBJ_DEFAULT_KEY,
                            loginTicket.getTicket());
                } else {
                    result.setSuccess(false);
                    result.setResultCode(LoginConstants.WS_PARAM_USER_ERROR_CODE);
                    result.addDefaultModel(BaseConstants.SERVICE_RETURN_MESSAGE_DEFAULT_KEY, LoginConstants.WS_PARAM_USER_ERROR_MESSAGE);
                    return result;
                }
            } else {
                result.setSuccess(false);
                result.setResultCode(LoginConstants.WS_PARAM_USER_ERROR_CODE);
                result.addDefaultModel(BaseConstants.SERVICE_RETURN_MESSAGE_DEFAULT_KEY, LoginConstants.WS_PARAM_USER_ERROR_MESSAGE);
                return result;
            }
        } catch (Exception e) {
            logger.error("LoginServiceImpl!login -> error!!", e);
            result.setSuccess(false);
            result.setResultCode(LoginConstants.SERVICE_RETURN_FALSE_CODE);
        }
        return result;
    }



    @Override
    public Result verifyTicket(TicketParam ticketParam) {
        Result result = new Result();
        try {
            //验证参数是否为空,为空返回自定义错误信息(Code 、 Message)
            if (null == ticketParam
                    || !StringUtils.validateStringNotNull(ticketParam.getTicket())
            ) {
                result.setSuccess(false);
                result.setResultCode(LoginConstants.WS_PARAM_OBJ_NULL_CODE);
                result.addDefaultModel(BaseConstants.SERVICE_RETURN_MESSAGE_DEFAULT_KEY, LoginConstants.WS_PARAM_OBJ_NULL_MESSAGE);
                return result;
            }
            LoginTicket loginTicket=loginTicketManager.getLoginTicket(ticketParam.getTicket());
            if (loginTicket == null) {
                result.setSuccess(false);
                result.setResultCode(LoginConstants.WS_PARAM_TICKET_ERROR_CODE);
                result.addDefaultModel(BaseConstants.SERVICE_RETURN_MESSAGE_DEFAULT_KEY, LoginConstants.WS_PARAM_TICKET_ERROR_MESSAGE);
                return result;
            }
            if (loginTicket.getExpireTime().before(new Date())) {
                result.setSuccess(false);
                result.setResultCode(LoginConstants.WS_PARAM_TICKET_ERROR_CODE);
                result.addDefaultModel(BaseConstants.SERVICE_RETURN_MESSAGE_DEFAULT_KEY, LoginConstants.WS_PARAM_TICKET_ERROR_MESSAGE);
                return result;
            }
            PerUsers perUsers = perUsersManager.getPerUsers(loginTicket.getUserCode());
            if (perUsers == null) {
                result.setSuccess(false);
                result.setResultCode(LoginConstants.WS_PARAM_TICKET_ERROR_CODE);
                result.addDefaultModel(BaseConstants.SERVICE_RETURN_MESSAGE_DEFAULT_KEY, LoginConstants.WS_PARAM_TICKET_ERROR_MESSAGE);
                return result;
            }
            if (perUsers.getUserStatus() == null || perUsers.getUserStatus() == 1) {
                result.setSuccess(false);
                result.setResultCode(LoginConstants.WS_PARAM_USER_STATUS_ERROR_CODE);
                result.addDefaultModel(BaseConstants.SERVICE_RETURN_MESSAGE_DEFAULT_KEY, LoginConstants.WS_PARAM_USER_STATUS_ERROR_MESSAGE);
                return result;
            }
            PerUsersDto perUsersVo = new PerUsersDto();
            perUsersVo.setId(perUsers.getId());
            perUsersVo.setUserCode(perUsers.getUserCode());
            //设置页面需要的对象
            result.setResultCode(BaseConstants.SERVICE_RESULT_SUCCESS_CODE);
            result.addDefaultModel(BaseConstants.SERVICE_RETURN_OBJ_DEFAULT_KEY, perUsersVo);
            result.setSuccess(true);
        } catch (Exception e) {
            logger.error("LoginServiceImpl!login -> error!!", e);
            result.setSuccess(false);
        }
        return result;
    }

    @Override
    public Result loginOut(TicketParam ticketParam) {
        Result result = new Result();
        try {
            //验证参数是否为空,为空返回自定义错误信息(Code 、 Message)
            if (null == ticketParam
                    || !StringUtils.validateStringNotNull(ticketParam.getTicket())
            ) {
                result.setSuccess(false);
                result.setResultCode(LoginConstants.WS_PARAM_OBJ_NULL_CODE);
                result.addDefaultModel(BaseConstants.SERVICE_RETURN_MESSAGE_DEFAULT_KEY, LoginConstants.WS_PARAM_OBJ_NULL_MESSAGE);
                return result;
            }
            LoginTicket loginTicket = new LoginTicket();
            // loginTicketManager.getLoginTicket(ticketParam.getTicket());
            if (loginTicket == null) {
                result.setSuccess(false);
                result.setResultCode(LoginConstants.WS_PARAM_TICKET_ERROR_CODE);
                result.addDefaultModel(BaseConstants.SERVICE_RETURN_MESSAGE_DEFAULT_KEY, LoginConstants.WS_PARAM_TICKET_ERROR_MESSAGE);
                return result;
            }
            LoginTicket update = new LoginTicket();
            update.setUpdateUser(loginTicket.getUserCode());
            update.setTicket(loginTicket.getTicket());
            // loginTicketManager.deleteTicket(update);
            //设置页面需要的对象
            result.setResultCode(BaseConstants.SERVICE_RESULT_SUCCESS_CODE);
            result.addDefaultModel(BaseConstants.SERVICE_RETURN_OBJ_DEFAULT_KEY, BaseConstants.SERVICE_RESULT_SUCCESS_MESSAGE);
            result.setSuccess(true);
        } catch (Exception e) {
            logger.error("LoginServiceImpl!loginOut -> error!!", e);
            result.setSuccess(false);
        }
        return result;
    }

    private String createTicket() throws NoSuchAlgorithmException {
        return DigestUtils.md5(RandomTokenUtils.createToken());
    }

    public void setExpireTime(Long expireTime) {
        this.expireTime = expireTime;
    }

    public void setPerUsersManager(PerUsersManager perUsersManager) {
        this.perUsersManager = perUsersManager;
    }

    public void setLoginTicketManager(LoginTicketManager loginTicketManager) {
        this.loginTicketManager = loginTicketManager;
    }

    public void setPerSysManager(PerSysManager perSysManager) {
        this.perSysManager = perSysManager;
    }
}

最后要在sprint mvc中配置登录拦截器

 <mvc:interceptors>
        <!-- 国际化操作拦截器 如果采用基于(请求/Session/Cookie)则必需配置 -->
        <bean class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor"/>
        <mvc:interceptor>
            <mvc:mapping path="/**"/>
            <bean class="com.jd.jdx.x.sr.aps.ui.controller.interceptor.LoginInterceptor">
                <property name="loginBusiness" ref="loginBusiness"/>
                <property name="prefixUrl" value="${page.prefix.url}"></property>
                <property name="excludePaths">
                    <list>
                        <value>/static/**</value>
                        <value>/user/**</value>
                        <value>/error/**</value>
                    </list>
                </property>
            </bean>
        </mvc:interceptor>
    </mvc:interceptors>

注意需要排除登录的action,不然会造成死循环,第二个注意点即使有二级域名也要直接配置到根路径,不然依然会循环登录

至此单点登录和登录拦截完成

原文地址:https://www.cnblogs.com/honghong75042/p/12467689.html