SpringSecurity授权方式学习(二)

本文详细介绍了如何使用Spring Security进行权限管理,包括基于路径的权限配置、基于角色的权限控制以及基于资源的权限管理。通过示例代码展示了如何配置HTTP请求的访问权限,以及如何结合数据库实现角色和资源的授权。同时,文中还提供了数据库表结构和相关查询方法,以实现用户登录后的权限获取。
摘要由CSDN通过智能技术生成
@Configuration
public class MySpringSecurityConfiguration extends WebSecurityConfigurerAdapter {
//配置权限校验,如:什么地址 必须认证后才能访问,什么地址可以不用认证就可以访问
        //权限校验的配置,是线性的。从开始的配置位置开始校验,成功立刻返回。
        //校验匹配失败,继续后续的逻辑校验
        /**
         *  Security的权限管理,是基于匹配路径后,授予权限的顺序规则。先通过表达式匹配当前请求路径地址
         *  在请求地址符合匹配逻辑的时候,授予访问权限
         * 常用的匹配请求路径的方法,执行顺序按照定义依次顺序执行,任何方法匹配,返回后续逻辑不执行
         * antMatchers      -   最常用,是基于 /*、/**等匹配符号,定义的表达式
         *      antMatchers(String...path);任意请求方式,都有效的匹配。参数传入的规则任意一个符合匹配逻辑都生效。
         *      antMatchers(HttpMethod method, String...path);限定了请求方式的匹配规则
         * regexMatchers    -   排斥,但是推荐使用,相对效率高。(正则表达式)
         *      regexMatchers(String...path);
         *      regexMatchers(HttpMethod method, String...path);
         * anyRequest       -   相当于 /** 的antMatchers匹配。任意请求地址
         *
         * 授予权限常用方法:
         *      permitAll()             -   免登录访问,任意用户任意状态都可以访问,描述通用和静态资源。如:首页,css,js,images
         *      anonymous()             -   匿名访问,登录后不可访问。   如:登录页面和登录请求
         *      authenticated()         -   登录后可以访问。描述保护资源:如:个人信息,订单查询等
         *      denyAll()               -   任意用户状态都不可访问
         *      fullyAuthenticated()    -   完整登录才可以访问。  描述敏感资源,如:支付操作
         *      rememberMe()            -   记住我,自动登录或N天免登录.描述非敏感资源,
         *  上述的所有方法底层调用的都是access();
         *      access()    -   可以实现任何权限授予逻辑。是基于权限表达式的权限授予方法
         *                      表达式规则由SpringSecurity定义
         *        表达式种类:
         *              1、定值表达式 access("permitAll") == permitAll()
         *                          包含:permitAll、anonymous、authenticated、fullyAuthenticated、denyAll、rememberMe
         */
        http.authorizeRequests()
                //.antMatchers("/toLogin").access("anonymous")    //只能匿名访问
                .antMatchers("/toLogin").anonymous()    //只能匿名访问
                .antMatchers("/failure", "/favicon.ico").permitAll()    //toLogin请求地址,可以随便访问
                .antMatchers("/**/*.js").permitAll()    //授予所有目录下的所有.js文件可访问资源
                .regexMatchers(".*[.]css").permitAll()  //授予所有目录下的所有.css文件可访问权限
                .anyRequest().authenticated();  //任意的请求必须认证后才可以访问

        //关闭CSRF安全协议,关闭是为了完整流程的可用
        http.csrf().disable();
    }
}

基于角色的权限管理

/*
 Navicat Premium Data Transfer

 Source Server         : MySQL
 Source Server Type    : MySQL
 Source Server Version : 80021
 Source Host           : localhost:3306
 Source Schema         : spring_security

 Target Server Type    : MySQL
 Target Server Version : 80021
 File Encoding         : 65001

 Date: 15/04/2021 10:09:05
*/

SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;

-- ----------------------------
-- Table structure for tb_resource
-- ----------------------------
DROP TABLE IF EXISTS `tb_resource`;
CREATE TABLE `tb_resource`  (
  `id` int(0) NOT NULL AUTO_INCREMENT,
  `res_name` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '权限名称',
  `res` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '权限描述符号, 如:admin:query	admin:create',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 5 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;

-- ----------------------------
-- Records of tb_resource
-- ----------------------------
INSERT INTO `tb_resource` VALUES (1, '管理员查询权限', 'admin:read');
INSERT INTO `tb_resource` VALUES (2, '管理员写权限', 'admin:write');
INSERT INTO `tb_resource` VALUES (3, '访客查询权限', 'guest:write');
INSERT INTO `tb_resource` VALUES (4, '访客写权限', 'guest:write');

-- ----------------------------
-- Table structure for tb_role
-- ----------------------------
DROP TABLE IF EXISTS `tb_role`;
CREATE TABLE `tb_role`  (
  `id` int(0) NOT NULL AUTO_INCREMENT,
  `role_name` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 3 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;

-- ----------------------------
-- Records of tb_role
-- ----------------------------
INSERT INTO `tb_role` VALUES (1, '管理员');
INSERT INTO `tb_role` VALUES (2, '访客');

-- ----------------------------
-- Table structure for tb_role_resource
-- ----------------------------
DROP TABLE IF EXISTS `tb_role_resource`;
CREATE TABLE `tb_role_resource`  (
  `role_id` int(0) NOT NULL,
  `resource_id` int(0) NOT NULL,
  PRIMARY KEY (`role_id`, `resource_id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;

-- ----------------------------
-- Records of tb_role_resource
-- ----------------------------
INSERT INTO `tb_role_resource` VALUES (1, 1);
INSERT INTO `tb_role_resource` VALUES (1, 2);
INSERT INTO `tb_role_resource` VALUES (2, 3);
INSERT INTO `tb_role_resource` VALUES (2, 4);

-- ----------------------------
-- Table structure for tb_user
-- ----------------------------
DROP TABLE IF EXISTS `tb_user`;
CREATE TABLE `tb_user`  (
  `id` int(0) NOT NULL AUTO_INCREMENT,
  `username` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
  `password` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
  PRIMARY KEY (`id`) USING BTREE,
  UNIQUE INDEX `username`(`username`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 4 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = DYNAMIC;

-- ----------------------------
-- Records of tb_user
-- ----------------------------
INSERT INTO `tb_user` VALUES (1, 'admin', '$2a$10$xAex8LhMiQDug1pBKHfRluWgKZQ4t.KpYk64qa5DS3taPVbRddvtu');
INSERT INTO `tb_user` VALUES (2, 'admin1', '$2a$10$cxrVP6O6F02Xsp8ypuY9mOnA9aCk96ql/f6xp9iV2ULghYTTNXo7W');
INSERT INTO `tb_user` VALUES (3, 'admin2', '$2a$10$WEs3VSfo3EY7kT3Ap6Q/auEjJOri57RYsJQLDZqDrVBrSea4hwFs2');

-- ----------------------------
-- Table structure for tb_user_role
-- ----------------------------
DROP TABLE IF EXISTS `tb_user_role`;
CREATE TABLE `tb_user_role`  (
  `user_id` int(0) NOT NULL,
  `role_id` int(0) NOT NULL,
  PRIMARY KEY (`user_id`, `role_id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;

-- ----------------------------
-- Records of tb_user_role
-- ----------------------------
INSERT INTO `tb_user_role` VALUES (1, 1);
INSERT INTO `tb_user_role` VALUES (2, 2);
INSERT INTO `tb_user_role` VALUES (3, 1);

SET FOREIGN_KEY_CHECKS = 1;
 //只根据用户名查询用户,密码的验证,在内存中处理。
    @Select("select * from tb_user where username = #{username}")
    User selectUserByUsername(String username);

    //根据用户主键查询角色名称  tb_role(role_name)
    @Select("select role_name from tb_role where id in (select role_id from tb_user_role where user_id = #{id})")
    List<String> selectRolesByUserId(Integer id);

    //根据用户主键,查询资源描述, tb_resource(res)
    @Select("select res from tb_resource where id in (select resource_id from tb_role_resource where role_id in (select role_id from tb_user_role where user_id = #{id}))")
    List<String> selectResourceByUserId(Integer id);
@Component
public class SpringSecurityConfiguration implements UserDetailsService {

    @Autowired
    private UserService userService;

    /**
     *
     * @param username 用户登录的用户名
     * @return
     * @throws UsernameNotFoundException    当用户查询失败的时候,抛出的异常
     */
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {

        User user = userService.login(username);
        if (user == null) {
            //查询失败,用户名不存在。抛出异常。
            throw new UsernameNotFoundException("用户名错误...");
        }
        /**
         * 查询成功,用户存储。需要匹配用户名密码是否正确。
         * 匹配密码,是由SpringSecurity内部逻辑自动完成。只需要把查询的用户名正确密码返回即可。
         * 返回结果,是UserDetails类型的实现类。可以自定义,可以使用Security框架。
         * security框架提供的UserDetails接口实现类型User,构造的时候,需要提供3个参数,或者7个参数。
         *      3参数构造:
         *              用户身份(用户名)、用户正确密码(数据库中的密码),权限集合(Collection集合)
         *      AuthorityUtils - 工具类,可以通过字符串,创建权限集合。
         */

        //新增:用户登录成功后,查询用户的权限集合,包括角色和权限

        //角色名称的集合
        List<String> roles = userService.findRolesByUser(user);
        //权限描述的集合
        List<String> resources = userService.findResourcesByUser(user);
        //在SpringSecurity中,对角色的命名的要求有严格的规则。要求角色名的前缀必须是ROLE_.不要在数据库中保存ROLE_角色名
        //处理角色名称问题
        String [] authorities = new String[roles.size() + resources.size()];
        for (int i = 0; i < roles.size(); i++) {
            authorities[i] = "ROLE_" + roles.get(i);
        }
        for (int i = 0; i < resources.size(); i++) {
            authorities[roles.size() + i] = resources.get(i);
        }
        System.out.println("用户:" + user.getUsername() + "的权限集合是:" + Arrays.toString(authorities));

        org.springframework.security.core.userdetails.User result
                = new org.springframework.security.core.userdetails.User(
                        username,
                        user.getPassword(),
                        AuthorityUtils.createAuthorityList(authorities));

        return result;
    }
}
http.authorizeRequests()
                //.antMatchers("/toLogin").access("anonymous")    //只能匿名访问
                .antMatchers("/toLogin").anonymous()    //只能匿名访问
                .antMatchers("/failure", "/favicon.ico").permitAll()    //toLogin请求地址,可以随便访问
                .antMatchers("/**/*.js").permitAll()    //授予所有目录下的所有.js文件可访问资源
                .regexMatchers(".*[.]css").permitAll()  //授予所有目录下的所有.css文件可访问权限
                //基于角色的权限管理
                //hasRole("XXX")相当于调用access("hasRole('ROLE_XXX')")
                .antMatchers("/admin/read").hasRole("管理员")  //请求地址为 /admin/read的请求,必须登录用户拥有'管理员'角色才能访问
                //hasAnyRole("x","y", "z")相当于调用access("hasAnyRole('ROLE_x','ROLE_y','ROLE_z')")
                .antMatchers("/guest/read").hasAnyRole("管理员", "访客")  //必须登录用户拥有'管理员'或'访客'角色才能访问
                .antMatchers("/guest/write").hasRole("访客")  //必须登录用户拥有'访客'角色才能访问
                .anyRequest().authenticated();  //任意的请求必须认证后才可以访问

        //关闭CSRF安全协议,关闭是为了完整流程的可用
        http.csrf().disable();
    }

基于资源的权限管理

http.authorizeRequests()
                //.antMatchers("/toLogin").access("anonymous")    //只能匿名访问
                .antMatchers("/toLogin").anonymous()    //只能匿名访问
                .antMatchers("/failure", "/favicon.ico").permitAll()    //toLogin请求地址,可以随便访问
                .antMatchers("/**/*.js").permitAll()    //授予所有目录下的所有.js文件可访问资源
                .regexMatchers(".*[.]css").permitAll()  //授予所有目录下的所有.css文件可访问权限
                //IP 规则访问需要完整匹配     localhost -> 0:0:0:0:0:0:0:1 -> ::1    127.0.0.1 -> 127.0.0.1
                //限制客户端的时候使用,如:提供给内部指定客户端的服务
                //客户端地址可以在请求头中查看,解析是由request.getRemoteIpAddr处理的
                //.antMatchers("/ip").access("hasIpAddress('::1')")       //使用access处理客户端
                .antMatchers("/ip").hasIpAddress("127.0.0.1")    //客户端IP符合规则的可以访问
                //基于资源的权限管理
                //hasAuthority("XXX")相当于access(hasAuthority("XXX"))
                .antMatchers("/admin/read").hasAuthority("admin:read")  //用于admin:read的权限的用户才可以访问
                .antMatchers("/admin/write").access("hasAuthority('admin:write')")
                .antMatchers("/guest/read").hasAnyAuthority("guest:read","admin:read")  //guest:read和admin:read权限的用户才可以访问

                //基于角色的权限管理
                //hasRole("XXX")相当于调用access("hasRole('ROLE_XXX')")
                //.antMatchers("/admin/read").hasRole("管理员")  //请求地址为 /admin/read的请求,必须登录用户拥有'管理员'角色才能访问
                //hasAnyRole("x","y", "z")相当于调用access("hasAnyRole('ROLE_x','ROLE_y','ROLE_z')")
                //.antMatchers("/guest/read").hasAnyRole("管理员", "访客")  //必须登录用户拥有'管理员'或'访客'角色才能访问
                //.antMatchers("/guest/write").hasRole("访客")  //必须登录用户拥有'访客'角色才能访问
                .anyRequest().authenticated();  //任意的请求必须认证后才可以访问

        //关闭CSRF安全协议,关闭是为了完整流程的可用
        http.csrf().disable();
    }

 

  • 4
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值