【Spring Security开发安全的REST服务】- 8-1课程总结

提前感慨

在这里插入图片描述

啊~~~~~~~~~总算看到这个章节了,一个章节一个章节看下来,由于使用的是和教程中不同的版本,所以遇到了很多关于版本迭代的不同点,各种查资料,问网友,哈哈哈,但是收获满满。

8.1.1、对之前的动态配置权限的小改动

教程中又创建了一个新的项目,然后演示了我们之前写的那些权限模块如何去使用,我这里暂不po出那部分的代码。仅仅在之前的Demo项目中对于需要修改的部分做简单的记录,以免忘记。

首先我们在之前的章节中遗留了一个问题,如下图所示
在这里插入图片描述
直接看代码
首先修改授权配置提供器AuthorizeConfigProvider中的返回类型

package com.moss.securitycore.authorize;

import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer;

/**
 *  授权配置提供器,各个模块和业务系统可以通过实现此接口向系统添加授权配置。
 *
 * @author lwj
 */
public interface AuthorizeConfigProvider {


    /**
     * 配置
     *
     * @param config 这个是配置类中的http.authorizeRequests()方法返回的对象
     */
//    void config(ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry config);
    /**
     * 配置
     *
     * @param config
     * @return 返回的boolean表示配置中是否有针对anyRequest的配置。在整个授权配置中,
     * 应该有且仅有一个针对anyRequest的配置,如果所有的实现都没有针对anyRequest的配置,
     * 系统会自动增加一个anyRequest().authenticated()的配置。如果有多个针对anyRequest
     * 的配置,则会抛出异常。
     */
    boolean config(ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry config);

}

修改权限配置提供器的默认实现类MossAuthorizeConfigProvider

package com.moss.securitycore.authorize;

import com.moss.securitycore.properties.SecurityConstants;
import com.moss.securitycore.properties.SecurityProperties;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.Order;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer;
import org.springframework.stereotype.Component;

/**
 * 权限配置提供器
 *
 * @author lwj
 */
@Component
@Order(Integer.MIN_VALUE)
public class MossAuthorizeConfigProvider implements AuthorizeConfigProvider {

    @Autowired
    private SecurityProperties securityProperties;

    @Override
    public boolean config(ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry config) {
        config.antMatchers(
                SecurityConstants.DEFAULT_UNAUTHENTICATION_URL,
                SecurityConstants.DEFAULT_LOGIN_PROCESSING_URL_MOBILE,
                securityProperties.getBrowser().getLoginPage(),
                SecurityConstants.DEFAULT_VALIDATE_CODE_URL_PREFIX + "/*",
                securityProperties.getBrowser().getSignUpUrl(),
                SecurityConstants.DEFAULT_SESSION_INVALID_URL,
                "/user/regist",
                "/auth/*",
                "/qqLogin/*",
                SecurityConstants.DEFAULT_LOGIN_PROCESSING_URL_OPEN_ID,
                SecurityConstants.DEFAULT_APP_SOCIAL_SIGNUP
        ).permitAll();

        //  由于退出登录的URL没有配置默认值,所以在这里需要判断一下
        if (StringUtils.isNotBlank(securityProperties.getBrowser().getSignOutUrl())) {
            config.antMatchers(securityProperties.getBrowser().getSignOutUrl()).permitAll();
        }
        return false;
    }

}

修改授权配置管理者实现类MossAuthorizeConfigManager

package com.moss.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.List;

/**
 * 授权配置管理者实现类
 * 用于把系统中的所有授权配置收集起来
 *
 * @author lwj
 */
@Component
public class MossAuthorizeConfigManager implements AuthorizeConfigManager {

    @Autowired
    private List<AuthorizeConfigProvider> authorizeConfigProviders;

    /**
     * @param config 这个是配置类中的http.authorizeRequests()方法返回的对象
     * @see com.moss.securitycore.authorize.AuthorizeConfigManager#config(org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer.ExpressionInterceptUrlRegistry)
     */
    @Override
    public void config(ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry config) {
        //  将所有的provider中配置的配置循环添加到项目的总配置中
        boolean existAnyRequestConfig = false;
        String existAnyRequestConfigName = null;

        for (AuthorizeConfigProvider authorizeConfigProvider : authorizeConfigProviders) {
            boolean currentIsAnyRequestConfig = authorizeConfigProvider.config(config);
            if (existAnyRequestConfig && currentIsAnyRequestConfig) {
                throw new RuntimeException("重复的anyRequest配置:" + existAnyRequestConfigName + ","
                        + authorizeConfigProvider.getClass().getSimpleName());
            } else if (currentIsAnyRequestConfig) {
                existAnyRequestConfig = true;
                existAnyRequestConfigName = authorizeConfigProvider.getClass().getSimpleName();
            }
        }

        if (!existAnyRequestConfig) {
            config.anyRequest().authenticated();
        }
    }

}

关键点!关键点!关键点!
重要的事情说三遍!上面的代码中包含的逻辑需要体会
然后下面的这段修改的代码中的中间的config配置也需要理解下;
下面我们配置了三种资源的不同权限要求
1.对于font资源我们使用了permitAll;因为这些是引用安全模块的系统中需要用到的资源文件,所以是不需要登录也可以被访问的
2.对于html页面和resource下的资源以及访问自身数据,是需要登录后才可以被访问
3.通过权限表达式的方式配置了一个从数据库中根据登录用户来动态获取数据,来判断用户是否有权限可以访问该资源
下面的三个配置中1和2并未在Demo项目中体现,这里主要式为了做例子展示。

package com.moss.securitydemo.security;


import com.moss.securitycore.authorize.AuthorizeConfigProvider;
import org.springframework.core.annotation.Order;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer;
import org.springframework.stereotype.Component;

/**
 * Demo项目的权限配置管理器
 *
 * @author lwj
 */
@Component
@Order(Integer.MAX_VALUE)
public class DemoAuthorizeConfigProvider implements AuthorizeConfigProvider {

    @Override
    public boolean config(ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry config) {
        config
                .antMatchers(HttpMethod.GET, "/fonts/**").permitAll()
                .antMatchers(HttpMethod.GET,
                        "/**/*.html",
                        "/admin/me",
                        "/resource").authenticated()
                .anyRequest()
                .access("@rbacService.hasPermission(request, authentication)");
        //  配置数据库的URL
        config.anyRequest().access("@rbacService.hasPermission(request,authentication)");
        //  由于上一行代码设置的是一个anyRequest所以这里需要设置返回为true
        return true;
    }

}

8.1.2、结语

代码千万行,我们需要去提升的是规范别人写代码的能力,而不是但一个学习一个功能的实现;就像授人以鱼不如授人以渔!

8.1.3、最后(贴上慕课网老师的源码)

https://github.com/MrMagicalJ/security

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值