springsecurity使用自定义登录过滤器实现并发session_woshihedayu的博客-程序员宅基地

技术标签: java  springsecurity  开发语言  

springsecurity中的相关配置如下

@Override
protected void configure(HttpSecurity http) throws Exception {
    
    http.exceptionHandling()
            .authenticationEntryPoint(new UnauthorizedEntryPoint())
            .and().csrf().disable()
            .authorizeRequests().antMatchers("/sys/faceLogin/**").permitAll()
            .anyRequest().authenticated()
            .and().logout(logout -> logout.deleteCookies("JSESSIONID")).logout().logoutUrl("/sys/logout")
            .addLogoutHandler(new TokenLogoutHandler()).and()
            .addFilter(tokenLoginFilter)
            .addFilter(faceLoginFilter)
            .addFilter(concurrentSessionFilter)
            .cors().configurationSource(corsConfigurationSource()).and()
            .sessionManagement().sessionAuthenticationStrategy(authenticationStrategy);
}

其中,tokenLoginFilter和faceLoginFilter是2个登录的过滤器。
相关的bean配置如下

@Bean
public HttpSessionEventPublisher httpSessionEventPublisher() {
    
    return new HttpSessionEventPublisher();
}

@Bean
public SessionRegistry sessionRegistry(){
    
    return new SessionRegistryImpl();
}

@Bean
public ConcurrentSessionFilter concurrentSessionFilter(SessionRegistry sessionRegistry){
    
    return new ConcurrentSessionFilter(sessionRegistry);
}

@Bean
public AuthenticationManager myAuthenticationManager() throws Exception {
    
    return authenticationManager();
}

@Bean
public TokenLoginFilter tokenLoginFilter(CompositeSessionAuthenticationStrategy strategy,AuthenticationManager authenticationManager){
    
    return new TokenLoginFilter(authenticationManager,strategy,userService);
}

@Bean
public FaceLoginFilter faceLoginFilter(CompositeSessionAuthenticationStrategy strategy,AuthenticationManager authenticationManager){
    
    return new FaceLoginFilter(userService,faceLoginService, strategy,authenticationManager);
}

@Bean
public ConcurrentSessionControlAuthenticationStrategy controlAuthenticationStrategy(SessionRegistry sessionRegistry){
    
    ConcurrentSessionControlAuthenticationStrategy strategy = new ConcurrentSessionControlAuthenticationStrategy(sessionRegistry);
    strategy.setMaximumSessions(1);
    return strategy;
}

@Bean
public SessionFixationProtectionStrategy sessionFixationProtectionStrategy(){
    
    return new SessionFixationProtectionStrategy();
}

@Bean
public RegisterSessionAuthenticationStrategy registerSessionAuthenticationStrategy(SessionRegistry sessionRegistry){
    
    return new RegisterSessionAuthenticationStrategy(sessionRegistry);
}

@Bean
public CompositeSessionAuthenticationStrategy sessionAuthenticationStrategy(List<SessionAuthenticationStrategy> authenticationStrategies){
    
    return new CompositeSessionAuthenticationStrategy(authenticationStrategies);
}

其中,strategy.setMaximumSessions(1);实现了一个用户只能在一个地方登录系统,不能在多个地方同时登录。
登录过滤器的代码如下

public class TokenLoginFilter extends UsernamePasswordAuthenticationFilter {
    

    private AuthenticationManager authenticationManager;

    private IUserService userService;

    public TokenLoginFilter(AuthenticationManager authenticationManager, SessionAuthenticationStrategy strategy, IUserService userService) {
    
        this.authenticationManager = authenticationManager;
        this.userService=userService;
        this.setRequiresAuthenticationRequestMatcher(new AntPathRequestMatcher("/sys/login","POST"));
        super.setSessionAuthenticationStrategy(strategy);
        super.setAuthenticationManager(authenticationManager);
    }

    @SneakyThrows
    @Override
    public Authentication attemptAuthentication(HttpServletRequest req, HttpServletResponse res)
            throws AuthenticationException {
    
        //获取表单提交的数据
        Map map = new ObjectMapper().readValue(req.getInputStream(), Map.class);
        String mobile = (String) map.get("mobile");
        String password = (String) map.get("password");
        return authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(mobile, password));
    }

    /**
     * 登录成功
     * @param request
     * @param response
     * @param chain
     * @param authResult
     * @throws IOException
     * @throws ServletException
     */
    @Override
    protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authResult) throws IOException, ServletException {
    
        SecurityUser securityUser = (SecurityUser) authResult.getPrincipal();
        User user=new User().setId(securityUser.getId()).setLevel(securityUser.getLevel());
        List<GrantedAuthority> authorities = userService.getPermsByUser(user).stream()
                .filter(permission -> permission.getType() == PermissionConstants.PY_API)
                .map(permission -> new SimpleGrantedAuthority(permission.getCode()))
                .collect(Collectors.toList());
        SecurityContextHolder.getContext().setAuthentication(new UsernamePasswordAuthenticationToken(securityUser,securityUser.getId(),authorities));
        ResponseUtil.out(response,Result.SUCCESS().setData(request.getSession().getId()));
    }

    /**
     * 登录失败
     * @param request
     * @param response
     * @param e
     * @throws IOException
     * @throws ServletException
     */
    @Override
    protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response,
                                              AuthenticationException e) throws IOException, ServletException {
    
        ResponseUtil.out(response, new Result(ResultCode.MOBILE_OR_PASSWORD_ERROR));
    }
}

其他具体配置细节详见官方文档
Session Management

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/woshihedayu/article/details/123424091

智能推荐

Java 反射机制_魔鬼啊魔鬼的博客-程序员宅基地

在运行状态中,对于任意一个类,都能够获取到这个类的所有属性和方法,对于任意一个对象,都能够调用它的任意一个方法和属性(包括私有的方法和属性),这种动态获取的信息以及动态调用对象的方法的功能就称为java语言的反射机制。通俗点讲,通过反射,该类对我们来说是完全透明的,想要获取任何东西都可以。Java反射机制获取调用类的构造器、方法、成员变量:public class ReflectDemo {...

【ParaView教程】第四章 常见问题 —— 怎样绘制二维翼型上压力系数Cp或马赫数Mach沿翼型的变化?__黄岛主_的博客-程序员宅基地_翼型表面压力系数

最终得到的结果:Cp和Mach在翼型表面上沿X方向的分布从上面的图片中可以看出数据是二维的,如果想要绘制二维翼型上压力系数Cp或马赫数Mach沿翼型的变化,首先需要将翼型的数据提取出来。读取测试数据test.vtk。 在test.vtk上应用Feature Edge过滤器,只选择Boundary Edges选项,这一步会将翼型和外边界同时提取出来。 在FeatureEdges1上应用Connectivity过滤器,Extract Mode选择Extract Clos...

js脚本系列(1) JS判断输入字符串长度(汉字算两个字符,字母数字算一个)_Stranger。的博客-程序员宅基地_英文算做2个字符js

汉字在数据库中占2个字符,如果输入字符超过数据库表字段长度,会出现错误,因此需要在前台进行判断。有两种方法进行判断:方法一:使用正则表达式,代码如下:function getByteLen(val) { var len = 0; for (var i = 0; i < val.length; i++) { v

**SpringMVC 笔记1 [共2篇]*_暗余的博客-程序员宅基地_springmvc 最全笔记详解

SpringMVC 笔记一 [共四篇,史上最全重点] @记得关注哦,持续更新自己的最全最精华笔记哦~今日内容:1.注意:* 三层架构是java特有的。 表现层|持久层|业务层;* MVC设计模式是很多语言所采用的;[只要是web开发,都会了解到MVC的设计模式]SpringMVC的开始:1. 三层架构:平时是C/S或B/S架构,我们平时做web开发是用B/S架构的开发;服务端就经常分...

资源收集贴(持续更新...)_weixin_30938149的博客-程序员宅基地

发现一些web资源,留下来,将来备查,现在还少,就不分类了。待将来多了再做分类1、国内的web服务资源,有不少好资源http://www.webxml.com.cn/zh_cn/index.aspx2、Twitter的资源搜索,(留着吧,不知道有没有用)http://search.twitter.com/search.rss?q={0}&amp;result_type=mixed3...

sqlite3入门基础、sqlite3常用函数_king_weng的博客-程序员宅基地_sqlite3函数

1、打开/创建一个数据库  int sqlite3_open(const char *filename,  sqlite3 **ppDb );功能:打开数据库链接参数:filename:数据库的路径和文件名ppdb:数据库句柄。返回:成功  SQLITE_OK (值为0),否则返回其他值。2、回调函数执行sql语句int sqlite3_exec(sqlite3* pDB...

随便推点

跨域访问_iteye_21250的博客-程序员宅基地

JavaScript跨域访问有多种方式:p3p跨域写cookie通过jsonp的方式跨域调用跨域post表单 Ajax跨域实现 [size=large][b]1.p3p跨域写cookie[/b][/size]先看hosts配置:[code=&quot;html&quot;]127.0.0.1 dev.operamasks.org127.0.0.1 plus.operamask....

oracle c3p0 死锁,C3P0老是莫名其妙就线程死锁,但不影响程序_weixin_39760433的博客-程序员宅基地

代码如下:2016-06-3022:40:38[WARN]-[Thread:C3P0PooledConnectionPoolManager[identityToken-&gt;1hge15w9h18tqorr1ltqcj|33d5cdd]-AdminTaskTimer]-[com.mchange.v2.async.ThreadPoolAsynchronousRunner$DeadlockDet...

matlab 电路频率响应_手把手教你如何设计一套电路原理图_weixin_39699163的博客-程序员宅基地

1、概述开关电源的设计是一份非常耗时费力的苦差事,需要不断地修正多个设计变量,直到性能达到设计目标为止。本文step-by-step 介绍反激变换器的设计步骤,并以一个6.5W 隔离双路输出的反激变换器设计为例,主控芯片采用NCP1015。基本的反激变换器原理图如图 1 所示,在需要对输入输出进行电气隔离的低功率(1W~60W)开关电源应用场合,反激变换器(Flyback Converter)是最...

java中RandomAccessFile类_旭旭_哥的博客-程序员宅基地

java中RandomAccessFile类主要用于读取和写入,好像只能以写入字符和整形的数据,有非常大的局限性读取时候字符转化为byte的形式,看代码怎么具体实现:package test;import java.io.File;import java.io.RandomAccessFile;public class RandomAccessFileDemo { public

服务器端socket使用流程_蜗牛_snail的博客-程序员宅基地

基于Socket的UDP和TCP编程介绍一、概述TCP(传输控制协议)和UDP(用户数据报协议是网络体系结构TCP/IP模型中传输层一层中的两个不同的通信协议。TCP:传输控制协议,一种面向连接的协议,给用户进程提供可靠的全双工的字节流,TCP套接口是字节流套接口(stream socket)的一种。UDP:用户数据报协议。UDP是一种无连接协议。UDP套接口是数据报套接口(da...

销售管理系统_谁说码农没头发的博客-程序员宅基地_销售管理系统

C语言-------销售管理系统一.需求分析A.功能需求很多商品销售机构都需要用到销售管理系统,商品信息包含的字段很多,比如包括:商品编号、商品名称、商品类别(普通电视机、DVD、带DVD的电视机,带DVD的电视机的售价为普通电视机和DVD单价之和的80%)、商品进货价格、商品销售价格、商品数量、供应商名称等。对系统的具体要求如下: 销售商品信息增删改查。 销售商品退货管理。 销售商品进货价格管理。 销售商品销售价格管理。 销售商品统计功能。 销售商品排序(价格)功能。B.技

推荐文章

热门文章

相关标签