V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
linuxsteam
V2EX  ›  Java

spring security 登录拦截(过滤) 那种更符合规范?

  •  
  •   linuxsteam · 2020-04-30 09:34:53 +08:00 · 5087 次点击
    这是一个创建于 1450 天前的主题,其中的信息可能已经有所发展或是发生改变。

    小弟最近刚刚研究 security 整合 jwt 想作为前后端分离的项目的后台

    看到网上的文章大概有两种 实现方式

    1. 建立两个过滤器, 一个用来拦截 /login,在 filter 里面写认证 然后进行返回 token 操作,另一个过滤器用来鉴权,拦截其他 URL 。
    2. 只建立一个鉴权过滤器,处理 /login 以外的请求. /login 写在 Controller 里,正常业务操作。跟这个老哥的实现思路一样 https://www.v2ex.com/t/544387

    小弟有几个疑问:

    1. JWT 这种属于 security 提供的 httpBasic 还是 formLogin 方式? (网上文章看到使用 formLogin 比较多一些,可能是因为它有自定义登录 URL 的方法。)
    2. 文中两种方案哪种更符合设计思想一些?
    第 1 条附言  ·  2020-04-30 17:12:32 +08:00

    贴下我最后的配置类吧,我使用的也是第一种方案。因为自己写的过滤器,formLogin,httpBasic,这两个人家封装好的处理方案,我全部禁用了

    public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    
        @Autowired
        private CustomAuthenticationProvider customAuthenticationProvider;
    
        @Autowired
        private RedisTemplate redisTemplate;
    
        /**
         * @param http
         * @throws Exception
         */
        @Override
        protected void configure(HttpSecurity http) throws Exception {
            ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry registry = http.authorizeRequests();
            registry.and()
                    .formLogin().disable()
                    .authorizeRequests()
                    .antMatchers("/user/login").permitAll()
                    .antMatchers("/user/register").permitAll()
                    .antMatchers("/admin").hasAnyRole("ADMIN")
                    // 任何请求 需要身份认证
                    .anyRequest().authenticated()
                    .and()
                    // 添加一个过滤 所有访问 /login 的请求给JWTLoginFilter处理 这个类处理所有的JWT相关内容
                    .addFilterBefore(new JWTLoginFilter("/user/login", HttpMethod.POST.toString(),authenticationManager(),redisTemplate), UsernamePasswordAuthenticationFilter.class)
                    // 添加一个过滤器,验证其他请求是否合法
                    .addFilterBefore(new JWTAuthenticationFilter(),UsernamePasswordAuthenticationFilter.class)
                    // 关闭跨站请求防护
                    .csrf().disable()
                    // 前后端分离采用JWT 不需要session
                    .sessionManagement().disable();
        }
    
        /**
         * @param auth
         * @throws Exception
         */
        @Override
        protected void configure(AuthenticationManagerBuilder auth) throws Exception {
            // 使用自定义身份验证组件
            auth.authenticationProvider(customAuthenticationProvider);
        }
    
        @Bean
        public Argon2PasswordEncoder passwordEncoder() {
            return new Argon2PasswordEncoder();
        }
    }
    
    
    23 条回复    2020-05-03 07:30:36 +08:00
    chenuu
        1
    chenuu  
       2020-04-30 10:04:33 +08:00
    我是用的第一种
    linuxsteam
        2
    linuxsteam  
    OP
       2020-04-30 10:33:31 +08:00
    @chenuu 也许咱们看的教程一样 哈哈。那你自定义 userDetailsService 了吗
    Oktfolio
        3
    Oktfolio  
       2020-04-30 10:47:33 +08:00
    /login 不用管,实现自己的 AuthenticationSuccessHandler 。然后 Jwt 鉴权过滤器。当然我自己还实现了一个 json 登录的过滤器。
    chenuu
        4
    chenuu  
       2020-04-30 11:26:59 +08:00
    @linuxsteam 定义了.metadatasource,voter 都有自定义.我这规则略复杂些
    linuxsteam
        5
    linuxsteam  
    OP
       2020-04-30 11:48:26 +08:00
    @Oktfolio 你实现了这个, 那你用的是 formLogin 方式吧?
    nvkou
        6
    nvkou  
       2020-04-30 11:50:42 +08:00 via Android
    千万别自定义。跟着行规走。不然后面上 sso 不好维护
    hantsy
        7
    hantsy  
       2020-04-30 12:00:11 +08:00
    Authentication 和 Authorization 两个不同的东西。
    1,Authentication 解决用户是否合法,可以使用 user/password, fingerprint, qrcode, onetimepassword 等方式。
    2, 拿到授权凭证后,比如 token(access_token, id_token), Authorization 是为了判断是否有相应的操作权限。
    EastLord
        8
    EastLord  
       2020-04-30 12:01:46 +08:00
    2
    JRay
        9
    JRay  
       2020-04-30 12:14:40 +08:00
    我也打算搞这套,准备用第二套方案
    JRay
        10
    JRay  
       2020-04-30 12:18:56 +08:00
    突然想到要是用 JWT 的话,强制下线这种操作怎么搞呢?这个是无状态的样,要是另外一个地方也保存了 JWT 强制下线就不好搞了
    bsg1992
        11
    bsg1992  
       2020-04-30 13:57:48 +08:00
    @JRay jwt 不能用作于中心化的授权场景。 有中心化的场景还是得采用 session 方式
    Guozi1989
        12
    Guozi1989  
       2020-04-30 16:31:51 +08:00
    @JRay 配合 redis 来做
    tang123456
        13
    tang123456  
       2020-04-30 16:45:07 +08:00
    目前我们公司用的是第一种,这两天搭项目我也用的第一种
    linuxsteam
        14
    linuxsteam  
    OP
       2020-04-30 17:08:09 +08:00
    @JRay 放到 redis 里,我现在写完了,发现跟 spring security 的初衷越来越远了
    linuxsteam
        15
    linuxsteam  
    OP
       2020-04-30 17:09:19 +08:00
    @tang123456 这种方式去写的话,感觉就用了 security 的令牌以及权限处理,认证几乎是自己写的吧(实现的自己的过滤器)
    securityCoding
        16
    securityCoding  
       2020-04-30 18:40:00 +08:00
    1.认证和鉴权是两件事情,第一种是对的
    2. @JRay 业务复杂度上来了都会走上 session 这条路
    3. 如果在用 spring-cloud 的话 ,我个人推荐还是通过 spring-cloud-gateway 网关自己写 filter 来实现, 把认证和鉴权这种业务无关的行为收拢到网关层面,将复杂度控制在网关层面 ,底层服务聚焦业务即可,只管读相关登录态属性(比如 uid...)
    securityCoding
        17
    securityCoding  
       2020-04-30 18:41:30 +08:00
    @linuxsteam 哈哈 , 写完发现都是自己的代码,还引入 security 这个复杂的组件...
    luckyrayyy
        18
    luckyrayyy  
       2020-04-30 18:45:14 +08:00 via iPhone
    我是第二种 login 放在 controller 里面。
    jwt 用的继承 httpbasic
    linuxsteam
        19
    linuxsteam  
    OP
       2020-04-30 20:04:08 +08:00
    @securityCoding 自己代码还算一般吧,就是比较费劲,如你所说:第一种使用 Security 比较多。
    我用的不是 cloud,是自己爱好写的。写完了,感觉有点泄劲哈哈
    Newyorkcity
        20
    Newyorkcity  
       2020-04-30 21:06:18 +08:00
    问下楼主学习 spring security 看什么文档?我看官方文档那么长,读了一两个小时了,我愣是没找到从数据库获取账户密码来进行验证的功能..
    iX8NEGGn
        21
    iX8NEGGn  
       2020-04-30 21:13:25 +08:00 via iPhone
    @Newyorkcity 这种是业务,security 不会帮你实现,你要自己实现 UserDetails 接口
    iX8NEGGn
        22
    iX8NEGGn  
       2020-04-30 21:15:39 +08:00 via iPhone
    @iX8NEGGn 说错了是 UserDetailsService 接口
    linuxsteam
        23
    linuxsteam  
    OP
       2020-05-03 07:30:36 +08:00 via Android
    @Newyorkcity 如果你想遵守官方得方式,重写 jdbcUserDetails 的方法(service,带不带 service 我忘记了)
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   935 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 29ms · UTC 19:54 · PVG 03:54 · LAX 12:54 · JFK 15:54
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.