【Spring Security OAuth2】- Security控制授权- 权限表达式

作者简介:大家好,我是smart哥,前中兴通讯、美团架构师,现某互联网公司CTO

联系qq:184480602,加我进群,大家一起学习,一起进步,一起对抗互联网寒冬

学习必须往深处挖,挖的越深,基础越扎实!

阶段1、深入多线程

阶段2、深入多线程设计模式

阶段3、深入juc源码解析


阶段4、深入jdk其余源码解析


阶段5、深入jvm源码解析

码哥源码部分

码哥讲源码-原理源码篇【2024年最新大厂关于线程池使用的场景题】

码哥讲源码【炸雷啦!炸雷啦!黄光头他终于跑路啦!】

码哥讲源码-【jvm课程前置知识及c/c++调试环境搭建】

​​​​​​码哥讲源码-原理源码篇【揭秘join方法的唤醒本质上决定于jvm的底层析构函数】

码哥源码-原理源码篇【Doug Lea为什么要将成员变量赋值给局部变量后再操作?】

码哥讲源码【你水不是你的错,但是你胡说八道就是你不对了!】

码哥讲源码【谁再说Spring不支持多线程事务,你给我抽他!】

终结B站没人能讲清楚红黑树的历史,不服等你来踢馆!

打脸系列【020-3小时讲解MESI协议和volatile之间的关系,那些将x86下的验证结果当作最终结果的水货们请闭嘴】

权限表达式

看源码得知,最后都会转成一个表达式,然后进行投票评估;
那么有哪些表达式呢?

这些表达式的由来,由代码中的配置而来。

    .antMatchers().xxx  每个函数都包装了一个表达式生成。
    
    跟着源码得到 返回的是一个  ExpressionUrlAuthorizationConfigurer.AuthorizedUrl 对象

202306181908263081.png

联合使用是通过access方法,自己写表达式

    .antMatchers("xx").access("hasRole('ROLE_USER') and hasRole('ROLE_SUPER')")

那么能自定义表达式,并且使用自己的代码逻辑来判定吗?是可以的,下一节讲解;

分离配置

如下配置,一部分是安全模块的配置,一部分是使用安全模块的应用自己的业务配置;

那么怎么能把这种业务配置分离出去呢?

    .antMatchers(
             SecurityConstants.DEFAULT_UNAUTHENTICATION_URL,
             SecurityConstants.DEFAULT_LOGIN_PROCESSING_URL_MOBILE,
             "/user/regist", // 注册请求,后面会介绍怎么把这个只有使用方知道放行的配置剥离处理
             // org.springframework.boot.autoconfigure.web.servlet.error.BasicErrorController
             // BasicErrorController 类提供的默认错误信息处理服务
             "/error",
             "/connect/*",
             "/auth/*",
             "/signin"
     )
     .permitAll()
     // 该路径,只允许有 ADMIN 角色的人访问
     .antMatchers(HttpMethod.GET, "/user/*").hasRole("ADMIN")

202306181908301132.png

思路:

  • 提供AuthorizeConfigProvider接口
  • 权限模块的通用配置实现该接口,然后进行配置
  • 其他的应用或则模块配置可以自己实现
  • 最后使用 AuthorizeConfigManager类来管理所有的AuthorizeConfigProvider实现
  • 拿到所有的配置后,进行统一设置

接口定义

    package cn.mrcode.imooc.springsecurity.securitycore.authorize;
    
    import org.springframework.security.config.annotation.web.builders.HttpSecurity;
    import org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer;
    
    /**
     * 权限自定义配置管理
     * @author : zhuqiang
     * @version : V1.0
     * @date : 2023/8/12 21:09
     */
    public interface AuthorizeConfigManager {
        void config(ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry config);
    }
    package cn.mrcode.imooc.springsecurity.securitycore.authorize;
    
    import org.springframework.security.config.annotation.web.builders.HttpSecurity;
    import org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer;
    
    /**
     * 自定义权限控制接口
     * @author : zhuqiang
     * @version : V1.0
     * @date : 2023/8/12 21:09
     */
    public interface AuthorizeConfigProvider {
        /**
         * @param config
         * @see HttpSecurity#authorizeRequests()
         */
        void config(ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry config);
    }

核心实现: 通用配置的抽取,只是把app和browser中用到的配置都抽到公用的里面了

    package cn.mrcode.imooc.springsecurity.securitycore.authorize;
    
    import cn.mrcode.imooc.springsecurity.securitycore.properties.SecurityConstants;
    import cn.mrcode.imooc.springsecurity.securitycore.properties.SecurityProperties;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.security.config.annotation.web.builders.HttpSecurity;
    import org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer;
    import org.springframework.stereotype.Component;
    
    /**
     * app和browser通用静态权限配置
     * @author : zhuqiang
     * @version : V1.0
     * @date : 2023/8/12 21:12
     */
    @Component
    public class CommonAuthorizeConfigProvider implements AuthorizeConfigProvider {
        @Autowired
        private SecurityProperties securityProperties;
    
        @Override
        public void config(ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry config) {
            config.antMatchers(
                    SecurityConstants.DEFAULT_UNAUTHENTICATION_URL,
                    SecurityConstants.DEFAULT_LOGIN_PROCESSING_URL_MOBILE,
                    SecurityConstants.DEFAULT_LOGIN_PROCESSING_URL_OPEN_ID,
                    SecurityConstants.DEFAULT_VALIDATE_CODE_URL_PREFIX + "/*",
                    securityProperties.getBrowser().getLoginPage(),
                    securityProperties.getBrowser().getSignUpUrl(),
                    securityProperties.getBrowser().getSession().getSessionInvalidUrl() + ".json",
                    securityProperties.getBrowser().getSession().getSessionInvalidUrl() + ".html"
            ).permitAll();
            // 退出成功处理,没有默认值,所以需要判定下
            String signOutUrl = securityProperties.getBrowser().getSignOutUrl();
            if (signOutUrl != null) {
                config.antMatchers(signOutUrl).permitAll();
            }
        }
    }
    package cn.mrcode.imooc.springsecurity.securitycore.authorize;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.security.config.annotation.web.builders.HttpSecurity;
    import org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer;
    import org.springframework.stereotype.Component;
    
    import java.util.Set;
    
    /**
     * @author : zhuqiang
     * @version : V1.0
     * @date : 2023/8/12 21:21
     */
    @Component
    public class DefaultAuthorizeConfigManager implements AuthorizeConfigManager {
        @Autowired
        private Set<AuthorizeConfigProvider> providers;
    
        @Override
        public void config(ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry config) {
            for (AuthorizeConfigProvider provider : providers) {
                provider.config(config);
            }
            // 除了上面配置的,其他的都需要登录后才能访问
            config.anyRequest().authenticated();
        }
    }

浏览器中的安全配置:

    // 有三个configure的方法,这里使用http参数的
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        applyPasswordAuthenticationConfig(http);
        SessionProperties session = securityProperties.getBrowser().getSession();
        http
                .apply(validateCodeSecurityConfig)
                .and()
                .apply(smsCodeAuthenticationSecurityConfigs)
                .and()
                .apply(imoocSocialSecurityConfig)
                .and()
                .rememberMe()
                .tokenRepository(persistentTokenRepository)
                .tokenValiditySeconds(securityProperties.getBrowser().getRememberMeSeconds())
                .userDetailsService(userDetailsService)
                .and()
                .sessionManagement()
                .invalidSessionStrategy(invalidSessionStrategy)
                .maximumSessions(session.getMaximumSessions())
                .maxSessionsPreventsLogin(session.isMaxSessionsPreventsLogin())
                .expiredSessionStrategy(sessionInformationExpiredStrategy)
                .and()
                .and()
                .logout()
                .logoutSuccessHandler(logoutSuccessHandler)
                .deleteCookies("JSESSIONID")
                .and()
                .csrf()
                .disable();
        // 注入进来,然后把调用下配置对象即可
        // 可以看到上面的配置都没有了http.authorizeRequests()的配置
        // 全部由具体的去实现配置了
        // app项目中的安全配置改动其实和这里一样
        authorizeConfigManager.config(http.authorizeRequests());
    }

demo项目的安全配置

    package com.example.demo.security;
    
    import cn.mrcode.imooc.springsecurity.securitycore.authorize.AuthorizeConfigProvider;
    import org.springframework.security.config.annotation.web.builders.HttpSecurity;
    import org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer;
    import org.springframework.stereotype.Component;
    
    /**
     * @author : zhuqiang
     * @version : V1.0
     * @date : 2023/8/12 21:25
     */
    @Component
    public class DemoAuthorizeConfigProvider implements AuthorizeConfigProvider {
        @Override
        public void config(ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry config) {
            config.antMatchers(
                    "/user/regist", // 注册请求
                    // org.springframework.boot.autoconfigure.web.servlet.error.BasicErrorController
                    // BasicErrorController 类提供的默认错误信息处理服务
                    "/error",
                    "/connect/*",
                    "/auth/*",
                    "/signin",
                    "/social/signUp",  // app注册跳转服务
                    "/swagger-ui.html",
                    "/swagger-ui.html/**",
                    "/webjars/**",
                    "/swagger-resources/**",
                    "/v2/**"
            )
                    .permitAll()
                    // 这里配置了一个不存在的角色。
                    // 可以访问下 看是否有效果
                    .antMatchers("/user/*").hasRole("xxx")
            ;
        }
    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值