Security 与响应式 webFlux(三) 完结撒花

本贴最后更新于 1538 天前,其中的信息可能已经时过境迁

前言

之前已经讲过 WebFlux 与 Security 的一种结合方式,又因为业务原因放弃了第一种实现的方式。

为了动态的 RBAC(Role-Based Access Control)接口级的权限管理和利用 Webflux 的吞吐和响应能力,又写另一种方式,这种方式放弃了一部分 Security 的能力,而利用自身的能力去书写,所以更加灵活,重要的是,已经把该踩的坑已经全部踩平,如有新坑,还望互相交流。

实践篇

Config 配置

之前已经写过,第一步需要配置 Scurity 的 Config,跟之前有一些区别

@EnableWebFluxSecurity
@EnableReactiveMethodSecurity
public class SecurityConfig {

    @Autowired
    private AuthenticationManager authenticationManager;

    @Autowired
    private SecurityContextRepository securityContextRepository;


    //security的鉴权排除列表
    private static final String[] excludedAuthPages = {
            "/auth/login",
            "/auth/logout"
    };

    @Bean
    SecurityWebFilterChain webFluxSecurityFilterChain(ServerHttpSecurity http) throws Exception {

        return http
		.exceptionHandling()
                .authenticationEntryPoint((swe, e) -> {
                    return Mono.fromRunnable(() -> {
                        swe.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
                    });
                }).accessDeniedHandler((swe, e) -> {
                    return Mono.fromRunnable(() -> {
                        swe.getResponse().setStatusCode(HttpStatus.FORBIDDEN);
                    });
                }).and()
                .csrf().disable()
                .formLogin().disable()
                .httpBasic().disable()
                .authenticationManager(authenticationManager)
                .securityContextRepository(securityContextRepository)
                .authorizeExchange()
                .pathMatchers(HttpMethod.OPTIONS).permitAll()
                .pathMatchers(excludedAuthPages).permitAll()
                .anyExchange().authenticated()
                .and().build();
    }
}

从上往下开始说明区别

1.增加认证异常处理,之前有登录成功与失败的类,现在已经不需要了,直接在配置遇到异常的处理方式

.authenticationEntryPoint : 认证失败进行 HTTP 401 状态码返回

.accessDeniedHandler : 访问被拒绝进行 HTTP 403 状态码返回

.formLogin : Security 登录认证功能关闭

.httpBasic : httpBasic 功能关闭

.authenticationManage : 重写认证管理,并进行配置

.securityContextRepository : 重写 Security 上下文存储库并进行配置(这个在上章提到过)

省下的配置都已经讲过了,就不多说了,配置根据自身业务需要在进行修改,有很多功能。

securityContextRepository 类

重写方法

总结

根据 Webflux 与 Security 的结合 网上资料比较少,并且往往不能结合现在的动态 RBAC 与分布式系统,在权限更加细粒化的需求的阶段,在以大型微服务为基础进行鉴权认证,保证速度、吞吐、响应为要求,希望能帮助有同样困惑的人。

ps:在上个月 2020 年 8 月 21 号 新的 oauth 来了!!!

Authorization Server 将替代 Spring Security OAuthSpring 社区提供 OAuth2.0 授权服务器支持。经过四个月的努力,Spring Authorization Server 项目中的 OAuth2.0 授权服务器开发库正式发布了第一个版本。

0.0.1 版本已经发布,在之前 Oauth2.0 比较难用的情况下,spring 从放弃 oauth 到社区回归 到迎接新的变化社区回归 到 0.0.1 的版本, 希望新版本的 oauth 系统 可以更加贴近现在服务变化所需要的东西。

之前的 Oauth 有很多不方便的地方,管理成本也比单纯的 Security 大,希望新版本能好用,之后放弃单纯的 Security 迎接新的 Oauth 授权,咱们之后的新 Oauth 见。

  • Security
    9 引用 • 15 回帖
  • OAuth

    OAuth 协议为用户资源的授权提供了一个安全的、开放而又简易的标准。与以往的授权方式不同之处是 oAuth 的授权不会使第三方触及到用户的帐号信息(如用户名与密码),即第三方无需使用用户的用户名与密码就可以申请获得该用户资源的授权,因此 oAuth 是安全的。oAuth 是 Open Authorization 的简写。

    36 引用 • 103 回帖 • 9 关注
  • Web
    116 引用 • 433 回帖 • 8 关注
  • RBAC
    4 引用 • 6 回帖

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...
  • 哈哈哈不需要配置多个认证服务,择优用之,很多时候没有必要走 oauth 那一套的。

    我开发微信小程序的时候也是前后端分离然后使用 jwe。自己写了一个过滤器进行 token 生成和获取,然后仅仅用 Spring Security OAuth Resource Server ,整个认证、授权的流程就完成了。加起来五六十十行代码(大多都是配置)。也就用到了他的 jose 和 resource server 两个模块而已。但是省掉了至少三个类,还不用自己去管理 Spring 的东西。

    互相学习哈 ~ 也可以看看我的关于 security 的文章,额,我指的是最新的一篇。其余的都过时了。

  • 其他回帖
  • lizhongyue248 1 评论

    @Vanessa 回帖的框框打字摁 ESC 就缩下去好难受啊。输入法字母输入错了摁 ESC 清空他就缩下去,我快哭了=-=

    Vanessa
  • 补一份用 spring security resource server 本地验证的来解析并认证 JWT 的配置,由于自己的项目已经在用了,不方便更改权限,不然可以分享出来一起学习

      @Bean
      fun springSecurityFilterChain(http: ServerHttpSecurity): SecurityWebFilterChain = http
          // Other Config......
          .oauth2ResourceServer { resourceServer ->
            resourceServer.jwt { jwt ->
              jwt.jwtAuthenticationConverter(grantedAuthoritiesExtractor())
            }
          }
          .csrf()
          .disable()
          .build()
    
      fun grantedAuthoritiesExtractor(): ReactiveJwtAuthenticationConverterAdapter {
        val jwtAuthenticationConverter = JwtAuthenticationConverter()
        jwtAuthenticationConverter.setJwtGrantedAuthoritiesConverter(GrantedAuthoritiesExtractor())
        return ReactiveJwtAuthenticationConverterAdapter(jwtAuthenticationConverter)
      }
    
      inner class GrantedAuthoritiesExtractor : Converter<Jwt, Collection<GrantedAuthority>> {
        override fun convert(jwt: Jwt): Collection<GrantedAuthority> {
          val authorities = jwt.claims
              .getOrDefault("roles", emptyList<JSONObject>()) as Collection<JSONObject>
          return authorities
              .map { role -> RoleGrantedAuthority(role) }
              .toList()
        }
      }
    

    可以看得出来自定义非常方案,对于默认只解析 scope 的方式稍微修改就适配了,十多行代码即可。自省端点也是很简单,以前撸过

    @Bean
      fun springSecurityFilterChain(http: ServerHttpSecurity): SecurityWebFilterChain = http
          .authorizeExchange { exchanges -> exchanges.anyExchange().access(securityAuthentication) }
          .oauth2ResourceServer { resourceServer ->
            resourceServer.opaqueToken { opaqueToken ->
              // Custom Opaque Token Introspector.
              opaqueToken.introspector(CustomAuthoritiesOpaqueTokenIntrospector())
            }
          }
          .csrf()
          .disable()
          .build()
    
    
      /**
       * Default, spring security will set authority from scopes.
       * But the system is access control from roles.
       * We need custom Opaque Token Introspector.
       */
      inner class CustomAuthoritiesOpaqueTokenIntrospector : ReactiveOpaqueTokenIntrospector {
        private val delegate: ReactiveOpaqueTokenIntrospector = NimbusReactiveOpaqueTokenIntrospector(
            opaqueTokenIntrospector.introspectionUri,
            opaqueTokenIntrospector.clientId,
            opaqueTokenIntrospector.clientSecret
        )
    
        override fun introspect(token: String): Mono<OAuth2AuthenticatedPrincipal> =
            delegate.introspect(token)
                .map { principal ->
                  // Build Principal
                  DefaultOAuth2AuthenticatedPrincipal(
                      principal.name, principal.attributes, extractAuthorities(principal))
                }
    
        private fun extractAuthorities(principal: OAuth2AuthenticatedPrincipal): Collection<GrantedAuthority> =
            // The authority from roles fields.
            (principal.getAttribute<List<JSONObject>>("roles") ?: emptyList())
                .map { role -> RoleGrantedAuthority(role) }
      }
    

    其他的还有很多,比如 JWT issue 验证,时间验证,有效期验证等等,官方都做好了的,直接用即可。

    现在对于 webflux,security 支持已经非常好了,不需要自定义那么多东西的。

    另外官方整合了 Nimbus 库,可以说是目前为止我用过最好用的了,JWS、JWE、JWK 等等。但是资料少,需要一定的官网文档阅读能力。

    3 操作
    lizhongyue248 在 2020-09-06 13:42:15 更新了该回帖
    lizhongyue248 在 2020-09-06 13:41:48 更新了该回帖
    lizhongyue248 在 2020-09-06 13:39:01 更新了该回帖
  • hong1yuan
    作者

    我们没有直接用 oauth2.0 是因为还得多配置个认证服务,考虑到微服务和高可用和一定的踩坑成本、并且暂时没有 SSO 单点登陆的需求,所以就没有采用。

    在 Spring Authorization Server 出现后在考虑版本稳定后有 SSO 相关的需求后踩踩坑。

    看了你的代码我感觉我可以在优化一下我的代码,有些地方处理的不太优雅,虽然完成了业务.....

    主要是网上这种结合资源太少,我看官网的文档也没找到很多有用的东西,可能是找的方向不太对,也可能是那堆英文快看头晕了

    还是得感谢你的建议,提升技术全靠道友~

    1 回复
  • 查看全部回帖

推荐标签 标签

  • Quicker

    Quicker 您的指尖工具箱!操作更少,收获更多!

    32 引用 • 130 回帖 • 2 关注
  • BND

    BND(Baidu Netdisk Downloader)是一款图形界面的百度网盘不限速下载器,支持 Windows、Linux 和 Mac,详细介绍请看这里

    107 引用 • 1281 回帖 • 27 关注
  • AngularJS

    AngularJS 诞生于 2009 年,由 Misko Hevery 等人创建,后为 Google 所收购。是一款优秀的前端 JS 框架,已经被用于 Google 的多款产品当中。AngularJS 有着诸多特性,最为核心的是:MVC、模块化、自动化双向数据绑定、语义化标签、依赖注入等。2.0 版本后已经改名为 Angular。

    12 引用 • 50 回帖 • 474 关注
  • QQ

    1999 年 2 月腾讯正式推出“腾讯 QQ”,在线用户由 1999 年的 2 人(马化腾和张志东)到现在已经发展到上亿用户了,在线人数超过一亿,是目前使用最广泛的聊天软件之一。

    45 引用 • 557 回帖 • 67 关注
  • Pipe

    Pipe 是一款小而美的开源博客平台。Pipe 有着非常活跃的社区,可将文章作为帖子推送到社区,来自社区的回帖将作为博客评论进行联动(具体细节请浏览 B3log 构思 - 分布式社区网络)。

    这是一种全新的网络社区体验,让热爱记录和分享的你不再感到孤单!

    132 引用 • 1114 回帖 • 124 关注
  • 锤子科技

    锤子科技(Smartisan)成立于 2012 年 5 月,是一家制造移动互联网终端设备的公司,公司的使命是用完美主义的工匠精神,打造用户体验一流的数码消费类产品(智能手机为主),改善人们的生活质量。

    4 引用 • 31 回帖 • 4 关注
  • 国际化

    i18n(其来源是英文单词 internationalization 的首末字符 i 和 n,18 为中间的字符数)是“国际化”的简称。对程序来说,国际化是指在不修改代码的情况下,能根据不同语言及地区显示相应的界面。

    8 引用 • 26 回帖
  • Eclipse

    Eclipse 是一个开放源代码的、基于 Java 的可扩展开发平台。就其本身而言,它只是一个框架和一组服务,用于通过插件组件构建开发环境。

    75 引用 • 258 回帖 • 617 关注
  • Logseq

    Logseq 是一个隐私优先、开源的知识库工具。

    Logseq is a joyful, open-source outliner that works on top of local plain-text Markdown and Org-mode files. Use it to write, organize and share your thoughts, keep your to-do list, and build your own digital garden.

    6 引用 • 63 回帖
  • OpenStack

    OpenStack 是一个云操作系统,通过数据中心可控制大型的计算、存储、网络等资源池。所有的管理通过前端界面管理员就可以完成,同样也可以通过 Web 接口让最终用户部署资源。

    10 引用 • 4 关注
  • 大数据

    大数据(big data)是指无法在一定时间范围内用常规软件工具进行捕捉、管理和处理的数据集合,是需要新处理模式才能具有更强的决策力、洞察发现力和流程优化能力的海量、高增长率和多样化的信息资产。

    93 引用 • 113 回帖
  • Chrome

    Chrome 又称 Google 浏览器,是一个由谷歌公司开发的网页浏览器。该浏览器是基于其他开源软件所编写,包括 WebKit,目标是提升稳定性、速度和安全性,并创造出简单且有效率的使用者界面。

    62 引用 • 289 回帖 • 1 关注
  • 星云链

    星云链是一个开源公链,业内简单的将其称为区块链上的谷歌。其实它不仅仅是区块链搜索引擎,一个公链的所有功能,它基本都有,比如你可以用它来开发部署你的去中心化的 APP,你可以在上面编写智能合约,发送交易等等。3 分钟快速接入星云链 (NAS) 测试网

    3 引用 • 16 回帖
  • 前端

    前端技术一般分为前端设计和前端开发,前端设计可以理解为网站的视觉设计,前端开发则是网站的前台代码实现,包括 HTML、CSS 以及 JavaScript 等。

    247 引用 • 1348 回帖
  • 小薇

    小薇是一个用 Java 写的 QQ 聊天机器人 Web 服务,可以用于社群互动。

    由于 Smart QQ 从 2019 年 1 月 1 日起停止服务,所以该项目也已经停止维护了!

    34 引用 • 467 回帖 • 742 关注
  • Kotlin

    Kotlin 是一种在 Java 虚拟机上运行的静态类型编程语言,由 JetBrains 设计开发并开源。Kotlin 可以编译成 Java 字节码,也可以编译成 JavaScript,方便在没有 JVM 的设备上运行。在 Google I/O 2017 中,Google 宣布 Kotlin 成为 Android 官方开发语言。

    19 引用 • 33 回帖 • 63 关注
  • SEO

    发布对别人有帮助的原创内容是最好的 SEO 方式。

    35 引用 • 200 回帖 • 22 关注
  • 服务器

    服务器,也称伺服器,是提供计算服务的设备。由于服务器需要响应服务请求,并进行处理,因此一般来说服务器应具备承担服务并且保障服务的能力。

    125 引用 • 588 回帖
  • abitmean

    有点意思就行了

    29 关注
  • VirtualBox

    VirtualBox 是一款开源虚拟机软件,最早由德国 Innotek 公司开发,由 Sun Microsystems 公司出品的软件,使用 Qt 编写,在 Sun 被 Oracle 收购后正式更名成 Oracle VM VirtualBox。

    10 引用 • 2 回帖 • 6 关注
  • RabbitMQ

    RabbitMQ 是一个开源的 AMQP 实现,服务器端用 Erlang 语言编写,支持多种语言客户端,如:Python、Ruby、.NET、Java、C、PHP、ActionScript 等。用于在分布式系统中存储转发消息,在易用性、扩展性、高可用性等方面表现不俗。

    49 引用 • 60 回帖 • 362 关注
  • CloudFoundry

    Cloud Foundry 是 VMware 推出的业界第一个开源 PaaS 云平台,它支持多种框架、语言、运行时环境、云平台及应用服务,使开发人员能够在几秒钟内进行应用程序的部署和扩展,无需担心任何基础架构的问题。

    5 引用 • 18 回帖 • 167 关注
  • 支付宝

    支付宝是全球领先的独立第三方支付平台,致力于为广大用户提供安全快速的电子支付/网上支付/安全支付/手机支付体验,及转账收款/水电煤缴费/信用卡还款/AA 收款等生活服务应用。

    29 引用 • 347 回帖
  • etcd

    etcd 是一个分布式、高可用的 key-value 数据存储,专门用于在分布式系统中保存关键数据。

    5 引用 • 26 回帖 • 528 关注
  • flomo

    flomo 是新一代 「卡片笔记」 ,专注在碎片化时代,促进你的记录,帮你积累更多知识资产。

    5 引用 • 107 回帖
  • C

    C 语言是一门通用计算机编程语言,应用广泛。C 语言的设计目标是提供一种能以简易的方式编译、处理低级存储器、产生少量的机器码以及不需要任何运行环境支持便能运行的编程语言。

    85 引用 • 165 回帖 • 1 关注
  • Openfire

    Openfire 是开源的、基于可拓展通讯和表示协议 (XMPP)、采用 Java 编程语言开发的实时协作服务器。Openfire 的效率很高,单台服务器可支持上万并发用户。

    6 引用 • 7 回帖 • 94 关注