用户可以在同一机器上反复登陆

来源:6-4 重构用户名密码登录

LayLowMay

2019-09-01

无论是browser版本下同一浏览器,还是app版本的同一deviceId下,用户在登陆成功后还是可以依旧访问loginProcessingUrl(authentication/form)再继续换用户名登陆或者登陆失败。
请问怎么防止这一情况

-----------------------------    以下是我想到的一些方法    -----------------------------

package com.imooc.security.core.authentication.anonymous;

import com.imooc.security.core.properties.SecurityConstants;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.AntPathMatcher;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/**
 * 指定url才进行判断,如果是匿名(未登陆状态)就允许通过,已登陆抛出异常不允许访问
 */
@Component("anonymousAllowFilter")
public class AnonymousAllowFilter extends OncePerRequestFilter implements InitializingBean {

    /**
     * 存放所有匿名允许通过的的url
     */
    private List<String> allowUrlList = new ArrayList<>();

    /**
     * 检查器,检查用户是否匿名(未登录)
     */
    @Autowired
    private AnonymousInspection inspection;

    /**
     * 验证请求url与配置的url是否匹配的工具类
     */
    private AntPathMatcher pathMatcher = new AntPathMatcher();

    @Autowired
    private AnonymousExceptionHandler handler;

    /**
     * 讲系统中配置的需要校验验证码的URL根据校验的类型放入map
     *
     * @param urlString
     */
    protected void addUrlToList(String urlString) {
        if (StringUtils.isNotBlank(urlString)) {
            String[] urls = StringUtils.splitByWholeSeparatorPreserveAllTokens(urlString, ",");
            for (String url : urls) {
                allowUrlList.add(url);
            }
        }
    }

    protected boolean isRequestMatch(HttpServletRequest request) {
        for (String url : allowUrlList) {
            if (pathMatcher.match(url, request.getRequestURI())) {
                return true;
            }
        }
        return false;
    }

    /**
     * 在其他参数组装完毕后,初始化urls这个值
     * @throws ServletException
     */
    @Override
    public void afterPropertiesSet() throws ServletException {
        super.afterPropertiesSet();

        allowUrlList.add(SecurityConstants.DEFAULT_SIGN_IN_PROCESSING_URL_FORM);
        allowUrlList.add(SecurityConstants.DEFAULT_SIGN_IN_PROCESSING_URL_MOBILE);
        allowUrlList.add(SecurityConstants.DEFAULT_SIGN_IN_PROCESSING_URL_OPENID);

        addUrlToList(inspection.urls());
    }

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws ServletException, IOException {
        try {
            if (isRequestMatch(request) && !inspection.anonymous()) {
                throw new AnonymousException("您已经登陆");
            }
        } catch (AnonymousException e) {
            handler.handle(request, response, e);
            return;
        }
        chain.doFilter(request, response);
    }
}

我根据老师您的课程写了一个过滤器摆在最前面,不知道这种解决方法好不好

写回答

1回答

JoJo

2019-09-03

额...没明白,为什么要防止?要防止的话自己判断下就好了,浏览器环境下登录成功后判断一下登录用户和session里的用户是否一致,app环境下判断一下deviceId就可以了。

0
1
LayLowMay
老师,我又修改了问题,用一个过滤器实现这个业务您看看这样写有没有比较符合您课程的风格,并且低耦合
2019-09-04
共1条回复

Spring Security技术栈开发企业级认证与授权

Spring Security技术栈,REST风格开发常见接口,独立开发认证授权模块保证REST服务安全

2662 学习 · 1561 问题

查看课程