SpringSecurity6 垃记

SpringSecurity6 垃记

直接上代码,明天再编辑

授权逻辑呢

主要是做了url鉴权,我存的是 system:user:list 转成了 /system/user/list

package com.kyokyo.system.config.security;

import jakarta.annotation.PostConstruct;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.security.authorization.AuthorityAuthorizationDecision;
import org.springframework.security.authorization.AuthorizationDecision;
import org.springframework.security.authorization.AuthorizationManager;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.web.access.intercept.RequestAuthorizationContext;
import org.springframework.stereotype.Component;

import java.util.*;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Supplier;
import java.util.stream.Collectors;

/**
 * @ClassName : CustomAuthorizationManager
 * @Description : 自定义AuthorizationManager
 * @Author : 段友元(duanyouyuan)
 * @Date: 2023年09月21日 18:27:09
 */
@Component
public class CustomAuthorizationManager<HttpServletRequest> implements AuthorizationManager<HttpServletRequest> {

    @Autowired
    private JdbcTemplate jdbcTemplate;

    /**
     * 接口权限映射
     */
    private static Map<String, List<GrantedAuthority>> interfacePermissionMappings = new HashMap<>();

    @Override
    public AuthorizationDecision check(Supplier<Authentication> authentication, HttpServletRequest request) {
        Authentication auth = authentication.get();
        if (null != auth && auth.isAuthenticated() && auth.getAuthorities().size() > 0) {
            RequestAuthorizationContext context = (RequestAuthorizationContext) request;
            String requestURI = context.getRequest().getRequestURI();
            List<GrantedAuthority> grantedAuthorities = interfacePermissionMappings.get(requestURI);
            for (GrantedAuthority authority : auth.getAuthorities()) {
                if (grantedAuthorities.contains(authority)) {
                    return new AuthorizationDecision(true);
                }
            }
        }
        return new AuthorizationDecision(false);
    }

    @PostConstruct
    public void init() {
        // 查出所有菜单、按钮类型的菜单 菜单类型(1.目录 2.菜单 3.按钮)
        String queryMenuSql = "select id,menu_perm from sys_menu where menu_type in ('2','3') and menu_perm != '' and menu_perm is not null";
        List<Map<String, Object>> menuMaps = jdbcTemplate.queryForList(queryMenuSql);
        // 使用菜单ID集合查询菜单及菜单需要的权限
        String queryRoleSql = """
                select menu_id,role_code from
                (select menu_id, role_id from sys_role_menu where menu_id in (:menuIds) ) t
                left join sys_role sr on role_id = sr.id
                """;
        MapSqlParameterSource param = new MapSqlParameterSource();
        param.addValue("menuIds", menuMaps.stream().map(m -> m.get("id")).collect(Collectors.toList()));

        NamedParameterJdbcTemplate template = new NamedParameterJdbcTemplate(jdbcTemplate);

        List<Map<String, Object>> roleMaps = template.queryForList(queryRoleSql, param);
        interfacePermissionMappings = roleMaps.stream()
                .collect(Collectors.groupingBy(m -> m.get("menu_id")))
                .entrySet().stream().map(entry -> {
                    Long menuId = (Long) entry.getKey();
                    AtomicReference<String> interfaceUrl = new AtomicReference<>("");
                    menuMaps.forEach(menu -> {
                        if (Objects.equals(menu.get("id"), menuId)) {
                            interfaceUrl.set(("/" + menu.get("menu_perm")).replaceAll(":", "/"));
                        }
                    });
                    List<Map<String, Object>> roles = entry.getValue();
                    List<GrantedAuthority> grantedAuthorities = new ArrayList<>();
                    roles.forEach(r -> {
                        SimpleGrantedAuthority authority = new SimpleGrantedAuthority("ROLE_" + r.get("role_code"));
                        grantedAuthorities.add(authority);
                    });
                    return new AbstractMap.SimpleEntry<>(interfaceUrl.get(), grantedAuthorities);
                }).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));

    }



}

配置呢

@Configuration
public class SecurityConfig {

    @Autowired
    private CustomAuthorizationManager customAuthorizationManager;

    @Bean
    SecurityFilterChain web(HttpSecurity http) throws Exception {
        http.formLogin(withDefaults());
        http.authorizeHttpRequests()
                .anyRequest()
                .access(customAuthorizationManager);

        // 获取工厂对象
        ApplicationContext applicationContext = http.getSharedObject(ApplicationContext.class);
        // 设置自定义URL权限处理
        /*http.apply(new AuthorizeHttpRequestsConfigurer<>(applicationContext))
                .withObjectPostProcessor(new ObjectPostProcessor<AuthorizationFilter>() {
                    @Override
                    public <O extends AuthorizationFilter> O postProcess(O object) {

                        return object;
                    }
                });*/
        return http.build();
    }


}

用户对象呢

package com.kyokyo.system.config.security;

import lombok.Data;
import lombok.experimental.Accessors;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;

import java.io.Serial;
import java.util.Collection;

/**
 * @Author: 段友元(duanyouyuan)
 * @Date: 2023年09月19 11:38:31
 * @Description: 自定义用户对象
 **/
@Accessors(chain = true)
@Data
public class CustomUserDetails implements UserDetails {

    @Serial
    private static final long serialVersionUID = 6150234099286074671L;

    /**
     * 主键
     */
    private Long id;

    /**
     * 账号
     */
    private String userAccount;

    /**
     * 密码
     */
    private String password;

    /**
     * 是否启用(1.是 0.否)
     */
    private Boolean enabled;

    /**
     * 是否删除(1.是 0.否)
     */
    private String deleteFlag;

    private Collection<? extends GrantedAuthority> authorities;

    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        return this.authorities;
    }

    @Override
    public String getPassword() {
        return this.password;
    }

    @Override
    public String getUsername() {
        return this.getUserAccount();
    }

    @Override
    public boolean isAccountNonExpired() {
        return true;
    }

    @Override
    public boolean isAccountNonLocked() {
        return true;
    }

    @Override
    public boolean isCredentialsNonExpired() {
        return true;
    }

    @Override
    public boolean isEnabled() {
        return this.enabled;
    }

}

查询用户对象呢

package com.kyokyo.system.config.security;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.kyokyo.system.user.entity.User;
import com.kyokyo.system.user.mapper.UserMapper;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @Author: 段友元(duanyouyuan)
 * @Date: 2023年09月19 11:41:29
 * @Description: 自定义用户接口
 **/
@Slf4j
@Service
public class CustomUserDetailsService implements UserDetailsService {

    @Autowired
    private UserMapper userMapper;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        User user = loadUserByUserName(username);
        if (null != user) {
            // 查询用户的角色编码集合
            List<String> roleCodes = loadRoleCodesByUserId(user.getId());
            Collection<? extends GrantedAuthority> authorities = new ArrayList<>();
            if (!CollectionUtils.isEmpty(roleCodes)) {
                authorities = roleCodes.stream().map(code -> new SimpleGrantedAuthority("ROLE_" + code)).collect(Collectors.toList());
            }
            return new CustomUserDetails()
                    .setUserAccount(user.getUserAccount())
                    .setPassword(user.getPassword())
                    .setEnabled(user.getEnabled())
                    .setAuthorities(authorities);
        } else {
            throw new UsernameNotFoundException("未找到该用户:" + username);
        }
    }


    /**
     * 描述:使用账号查询用户信息
     * @author 段友元(duanyouyuan)
     * @param userName 账号
     * @return com.kyokyo.system.user.entity.User
     * @create 2023年09月19日 11:54:01
    **/
    private User loadUserByUserName(String userName) {
        return new LambdaQueryChainWrapper<>(userMapper).eq(User::getUserAccount, userName).one();
    }

    /**
     * 描述:使用用户 ID查询用户角色编码集合
     * @author 段友元(duanyouyuan)
     * @param userId 用户 ID
     * @return java.util.List<java.lang.String>
     * @create 2023年09月19日 14:18:58
    **/
    private List<String> loadRoleCodesByUserId(Long userId) {
        return userMapper.selectRoleCodesByUser(userId);
    }

}

建表语句

/*
 Navicat Premium Data Transfer

 Source Server         : 本机服务
 Source Server Type    : MySQL
 Source Server Version : 80030
 Source Host           : localhost:3306
 Source Schema         : kyokyo-boot

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

 Date: 21/09/2023 23:24:35
*/

SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;

-- ----------------------------
-- Table structure for sys_menu
-- ----------------------------
DROP TABLE IF EXISTS `sys_menu`;
CREATE TABLE `sys_menu`  (
  `id` bigint NOT NULL COMMENT '主键',
  `parent_id` bigint NOT NULL COMMENT '父级主键',
  `menu_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '菜单名',
  `menu_code` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '菜单编码',
  `menu_type` varchar(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '菜单类型(1.目录 2.菜单 3.按钮)',
  `component_path` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '组件路径',
  `menu_perm` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '菜单权限',
  `menu_sort` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '菜单顺序',
  `menu_desc` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '描述',
  `enabled` varchar(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '是否启用(1.是 0.否)',
  `remark` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '备注',
  `delete_flag` varchar(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '是否删除(1.是 0.否)',
  `created_by` bigint NULL DEFAULT NULL COMMENT '创建人',
  `created_time` datetime NULL DEFAULT NULL COMMENT '创建时间',
  `updated_by` bigint NULL DEFAULT NULL COMMENT '更新人',
  `updated_time` datetime NULL DEFAULT NULL COMMENT '更新时间',
  PRIMARY KEY (`id`) USING BTREE,
  INDEX `idx_parent_id`(`parent_id` ASC) USING BTREE COMMENT '父级主键',
  INDEX `idx_menu_code`(`menu_code` ASC) USING BTREE COMMENT '菜单编码'
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '菜单表' ROW_FORMAT = DYNAMIC;

-- ----------------------------
-- Records of sys_menu
-- ----------------------------
INSERT INTO `sys_menu` VALUES (1, 0, '系统管理', 'system', '1', NULL, NULL, '100', NULL, '1', NULL, '0', 1, '2023-09-19 09:44:58', 1, '2023-09-19 09:45:02');
INSERT INTO `sys_menu` VALUES (2, 0, '库存管理', 'inventory', '1', NULL, NULL, '200', NULL, '1', NULL, '0', 1, '2023-09-19 09:44:58', 1, '2023-09-19 09:45:02');
INSERT INTO `sys_menu` VALUES (1001, 1, '用户管理', 'user', '2', 'system/user/index', 'system:user:list', '100', NULL, '1', NULL, '0', 1, '2023-09-19 09:44:58', 1, '2023-09-19 09:45:02');
INSERT INTO `sys_menu` VALUES (1002, 1, '角色管理', 'role', '2', 'system/role/index', 'system:role:list', '200', NULL, '1', NULL, '0', 1, '2023-09-19 09:44:58', 1, '2023-09-19 09:45:02');
INSERT INTO `sys_menu` VALUES (1003, 1, '菜单管理', 'menu', '2', 'system/menu/index', 'system:menu:list', '300', NULL, '1', NULL, '0', 1, '2023-09-19 09:44:58', 1, '2023-09-19 09:45:02');

-- ----------------------------
-- Table structure for sys_role
-- ----------------------------
DROP TABLE IF EXISTS `sys_role`;
CREATE TABLE `sys_role`  (
  `id` bigint NOT NULL COMMENT '主键',
  `role_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '角色名',
  `role_code` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '角色编码',
  `role_desc` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '角色描述',
  `enabled` varchar(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '是否启用(1.是 0.否)',
  `remark` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '备注',
  `delete_flag` varchar(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '是否删除(1.是 0.否)',
  `created_by` bigint NULL DEFAULT NULL COMMENT '创建人',
  `created_time` datetime NULL DEFAULT NULL COMMENT '创建时间',
  `updated_by` bigint NULL DEFAULT NULL COMMENT '更新人',
  `updated_time` datetime NULL DEFAULT NULL COMMENT '更新时间',
  PRIMARY KEY (`id`) USING BTREE,
  INDEX `idx_role_code`(`role_code` ASC) USING BTREE COMMENT '角色编码'
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '角色表' ROW_FORMAT = DYNAMIC;

-- ----------------------------
-- Records of sys_role
-- ----------------------------
INSERT INTO `sys_role` VALUES (1, '超级管理员', 'admin', '超级管理员', '1', NULL, '0', 1, '2023-09-19 09:44:58', 1, '2023-09-19 09:45:02');
INSERT INTO `sys_role` VALUES (2, '维护工程师', 'maintenance', '维护工程师', '1', NULL, '0', 1, '2023-09-19 09:44:58', 1, '2023-09-19 09:45:02');
INSERT INTO `sys_role` VALUES (3, '普通用户', 'normal', '普通用户', '1', NULL, '0', 1, '2023-09-19 09:44:58', 1, '2023-09-19 09:45:02');

-- ----------------------------
-- Table structure for sys_role_menu
-- ----------------------------
DROP TABLE IF EXISTS `sys_role_menu`;
CREATE TABLE `sys_role_menu`  (
  `id` bigint NOT NULL COMMENT '主键',
  `role_id` bigint NOT NULL COMMENT '用户ID',
  `menu_id` bigint NOT NULL COMMENT '角色ID',
  `delete_flag` varchar(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '是否删除(1.是 0.否)',
  `created_by` bigint NULL DEFAULT NULL COMMENT '创建人',
  `created_time` datetime NULL DEFAULT NULL COMMENT '创建时间',
  `updated_by` bigint NULL DEFAULT NULL COMMENT '更新人',
  `updated_time` datetime NULL DEFAULT NULL COMMENT '更新时间',
  PRIMARY KEY (`id`) USING BTREE,
  INDEX `idx_role_id`(`role_id` ASC) USING BTREE COMMENT '角色主键',
  INDEX `idx_menu_id`(`menu_id` ASC) USING BTREE COMMENT '菜单主键'
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '角色菜单中间表' ROW_FORMAT = DYNAMIC;

-- ----------------------------
-- Records of sys_role_menu
-- ----------------------------
INSERT INTO `sys_role_menu` VALUES (1, 1, 1001, '0', 1, '2023-09-19 09:44:58', 1, '2023-09-19 09:45:02');
INSERT INTO `sys_role_menu` VALUES (2, 2, 1001, '0', 1, '2023-09-19 09:44:58', 1, '2023-09-19 09:45:02');

-- ----------------------------
-- Table structure for sys_user
-- ----------------------------
DROP TABLE IF EXISTS `sys_user`;
CREATE TABLE `sys_user`  (
  `id` bigint NOT NULL COMMENT '主键',
  `user_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '用户名',
  `user_account` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '账号',
  `password` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '密码',
  `user_desc` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '描述',
  `enabled` varchar(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '是否启用(1.是 0.否)',
  `remark` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '备注',
  `delete_flag` varchar(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '是否删除(1.是 0.否)',
  `created_by` bigint NULL DEFAULT NULL COMMENT '创建人',
  `created_time` datetime NULL DEFAULT NULL COMMENT '创建时间',
  `updated_by` bigint NULL DEFAULT NULL COMMENT '更新人',
  `updated_time` datetime NULL DEFAULT NULL COMMENT '更新时间',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '用户表' ROW_FORMAT = DYNAMIC;

-- ----------------------------
-- Records of sys_user
-- ----------------------------
INSERT INTO `sys_user` VALUES (1, '段友元', 'kyokyo', '{noop}123456', '开发账号', '1', NULL, '0', 1, '2023-09-19 09:42:33', 1, '2023-09-19 09:42:35');
INSERT INTO `sys_user` VALUES (2, '貂蝉', 'diaochan', '{noop}123456', '开发账号', '1', NULL, '0', 1, '2023-09-19 09:42:33', 1, '2023-09-19 09:42:35');
INSERT INTO `sys_user` VALUES (3, '西施', 'xishi', '{noop}123456', '开发账号', '1', NULL, '0', 1, '2023-09-19 09:42:33', 1, '2023-09-19 09:42:35');

-- ----------------------------
-- Table structure for sys_user_role
-- ----------------------------
DROP TABLE IF EXISTS `sys_user_role`;
CREATE TABLE `sys_user_role`  (
  `id` bigint NOT NULL COMMENT '主键',
  `user_id` bigint NOT NULL COMMENT '用户ID',
  `role_id` bigint NOT NULL COMMENT '角色ID',
  `delete_flag` varchar(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '是否删除(1.是 0.否)',
  `created_by` bigint NULL DEFAULT NULL COMMENT '创建人',
  `created_time` datetime NULL DEFAULT NULL COMMENT '创建时间',
  `updated_by` bigint NULL DEFAULT NULL COMMENT '更新人',
  `updated_time` datetime NULL DEFAULT NULL COMMENT '更新时间',
  PRIMARY KEY (`id`) USING BTREE,
  INDEX `idx_user_id`(`user_id` ASC) USING BTREE COMMENT '用户主键',
  INDEX `idx_role_id`(`role_id` ASC) USING BTREE COMMENT '角色主键'
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '用户角色中间表' ROW_FORMAT = DYNAMIC;

-- ----------------------------
-- Records of sys_user_role
-- ----------------------------
INSERT INTO `sys_user_role` VALUES (1, 1, 1, '0', 1, '2023-09-19 09:44:58', 1, '2023-09-19 09:45:02');
INSERT INTO `sys_user_role` VALUES (2, 2, 2, '0', 1, '2023-09-19 09:44:58', 1, '2023-09-19 09:45:02');
INSERT INTO `sys_user_role` VALUES (3, 3, 3, '0', 1, '2023-09-19 09:44:58', 1, '2023-09-19 09:45:02');

SET FOREIGN_KEY_CHECKS = 1;

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值