SpringSecurity认证授权具体流程步骤(具体实例)

news2024/11/17 7:24:16

本案例是通过使用SpringSecurity来实现通过读取数据库中的数据,来完成认证授权的案例。

1. 向数据库中添加具体实例

创建出五个表,五个表之间的关系为:
sys_user:登录表,用于登陆后查询id
sys_user_role:用于根据用用户的id来查询到role_ id
sys_role_function:用于通过role_id来查询对应的fun_id
sys_function:用于通过fun_id来查询对应的方法,以及fun_code方法权限

DROP TABLE IF EXISTS `sys_function`;
CREATE TABLE `sys_function` (
  `id` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
  `fun_name` varchar(50) DEFAULT NULL,
  `fun_url` varchar(50) DEFAULT NULL,
  `fun_code` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3;

-- ----------------------------
-- Records of sys_function
-- ----------------------------
INSERT INTO `sys_function` VALUES ('1', '商品列表查询', '/goods/list', 'goods:list');
INSERT INTO `sys_function` VALUES ('2', '商品添加', '/goods/add', 'goods:add');
INSERT INTO `sys_function` VALUES ('3', '商品删除', '/goods/del', 'goods:del');
INSERT INTO `sys_function` VALUES ('4', '商品更新', '/goods/update', 'goods:update');

-- ----------------------------
-- Table structure for `sys_role`
-- ----------------------------
DROP TABLE IF EXISTS `sys_role`;
CREATE TABLE `sys_role` (
  `id` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
  `rname` varchar(50) DEFAULT NULL,
  `rcode` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
  `rdesc` varchar(100) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3;

-- ----------------------------
-- Records of sys_role
-- ----------------------------
INSERT INTO `sys_role` VALUES ('1', '管理员', 'admin', null);
INSERT INTO `sys_role` VALUES ('2', '普通用户', 'user', null);

-- ----------------------------
-- Table structure for `sys_role_function`
-- ----------------------------
DROP TABLE IF EXISTS `sys_role_function`;
CREATE TABLE `sys_role_function` (
  `id` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
  `role_id` varchar(50) DEFAULT NULL,
  `fun_id` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3;

-- ----------------------------
-- Records of sys_role_function
-- ----------------------------
INSERT INTO `sys_role_function` VALUES ('1', '1', '1');
INSERT INTO `sys_role_function` VALUES ('2', '1', '2');
INSERT INTO `sys_role_function` VALUES ('3', '1', '3');
INSERT INTO `sys_role_function` VALUES ('4', '1', '4');
INSERT INTO `sys_role_function` VALUES ('5', '2', '1');

-- ----------------------------
-- Table structure for `sys_user`
-- ----------------------------
DROP TABLE IF EXISTS `sys_user`;
CREATE TABLE `sys_user` (
  `id` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
  `uname` varchar(30) DEFAULT NULL,
  `upwd` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
  `uemail` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
  `uphone` char(11) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3;

-- ----------------------------
-- Records of sys_user
-- ----------------------------
INSERT INTO `sys_user` VALUES ('a', 'admin', '$2a$10$tUBtEISZ/BkzQl0IJ6faOOZf6E1udcN9NsALobz2ofqooUPKUbm0K', null, '15516197242');
INSERT INTO `sys_user` VALUES ('b', 'anne', '$2a$10$tUBtEISZ/BkzQl0IJ6faOOZf6E1udcN9NsALobz2ofqooUPKUbm0K', null, '15516197241');

-- ----------------------------
-- Table structure for `sys_user_role`
-- ----------------------------
DROP TABLE IF EXISTS `sys_user_role`;
CREATE TABLE `sys_user_role` (
  `id` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
  `user_id` varchar(50) DEFAULT NULL,
  `role_id` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3;

-- ----------------------------
-- Records of sys_user_role
-- ----------------------------
INSERT INTO `sys_user_role` VALUES ('1', 'a', '1');
INSERT INTO `sys_user_role` VALUES ('2', 'b', '2');

2.项目的具体结构

在这里插入图片描述

3.添加相关的依赖,主要使用SpringBoot以及Mybatis_Plus,以及application.yml配置

 <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.3.9.RELEASE</version>
    </parent>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>

        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>1.2.6</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version> 3.5.2</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
    </dependencies>

application.yml:

server:
  port: 9007

spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/security_db?serverTimezone=Asia/Shanghai
    username: root
    password: 123456
    #      连接池的类型
    type: com.alibaba.druid.pool.DruidDataSource
    druid:
      initial-size: 5
      max-active: 100
      min-idle: 10

4 .主要代码理解

①:项目中的mapper层,entiity层,service层以及实现类是通过mybatis_plus的相关注解,不再赘述。
②:创建对应的CusUserDetailsServiceImpl实现类,LoginUser实体类来完成对数据库中数据的读取。

LoginUser实体类:
该实体类要实现UserDetails的接口,来实现里面的方法,getAuthorities()方法主要是获取授权的权限:SimpleGrantedAuthority是查看GrantedAuthority的具体实现类来写的。(查看底层的逻辑)。

ArrayList<SimpleGrantedAuthority> strings = new ArrayList<>();
    for (Function function : functionList) {
        strings.add(new SimpleGrantedAuthority(function.getFunCode()));
    }
    return strings;
public class LoginUser implements UserDetails {
    private User user;
    private List<Function> functionList;

    public LoginUser(User user, List<Function> functionList) {
        this.user = user;
        this.functionList = functionList;
    }

    /**
     * 获取登录的用户 拥有哪些权限
     *
     * @return
     */
    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        ArrayList<SimpleGrantedAuthority> strings = new ArrayList<>();
        for (Function function : functionList) {
            strings.add(new SimpleGrantedAuthority(function.getFunCode()));
        }
        return strings;
    }

    @Override
    public String getPassword() {
        return user.getUpwd();
    }

    @Override
    public String getUsername() {
        return user.getUname();
    }

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

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

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

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

CusUserDetailsServiceImpl实现类:
在这个类中,通过我们数据库中表的相关逻辑在实现类中实现相对应的方法。来查询我们所需要的loginUser。

@Service
public class CusUserDetailsServiceImpl implements UserDetailsService {
    @Resource
    private UserService userService;

    @Resource
    private UserRoleService userRoleService;

    @Resource
    private RoleFunctionService roleFunctionService;

    @Resource
    private FunctionService functionService;

    /**
     * 从何处 去加载一个用户
     *
     * @param s
     * @return
     * @throws UsernameNotFoundException
     */
    @Override
    public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {
        User user = userService.getUserByName(s);
        String userId = user.getId();
//     根据用户id 去查询 角色
        List<String> roleIds = userRoleService.getRoleByUserId(userId);
//        根据roleId  去找 functionId
        List<String> functionIds = roleFunctionService.getFunctionByRoleIds(roleIds);
//        根据functionId 去找function
        List<Function> functions = functionService.listByIds(functionIds);
//
        LoginUser loginUser = new LoginUser(user, functions);
        return loginUser;
    }
}

③:完成SpringSecurity的配置类:
我们是基于session来实现的。前端使用postman来返回表单的数据。
SecurityConfig.java

@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true,jsr250Enabled = true,securedEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Bean
    public PasswordEncoder passwordEncoder(){
        return  new BCryptPasswordEncoder();
    }

    public NamePassFilter namePassFilter() throws Exception {
        NamePassFilter namePassFilter = new NamePassFilter();
        //交给拦截管理器来进行处理
        namePassFilter.setAuthenticationManager(authenticationManagerBean());
        //设置拦截路径为/login
        namePassFilter.setFilterProcessesUrl("/login");

//        认证成功
        namePassFilter.setAuthenticationSuccessHandler(new AuthenticationSuccessHandler() {
            @Override
            public void onAuthenticationSuccess(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Authentication authentication) throws IOException, ServletException {
                httpServletResponse.setContentType("application/json;charset=utf-8");
                HashMap<String, Object> hashMap = new HashMap<>();
                hashMap.put("status", "200");
                hashMap.put("msg", "认证成功");
                hashMap.put("auth", authentication);
                httpServletResponse.getWriter().write(new ObjectMapper().writeValueAsString(hashMap));
            }
        });
//        认证失败
        namePassFilter.setAuthenticationFailureHandler(new AuthenticationFailureHandler() {
            @Override
            public void onAuthenticationFailure(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AuthenticationException e) throws IOException, ServletException {
                httpServletResponse.setContentType("application/json;charset=utf-8");
                httpServletResponse.getWriter().write("认证失败了" + e.getMessage());
            }
        });
        return namePassFilter;
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests().anyRequest().authenticated();
        http.addFilterAt(namePassFilter(), UsernamePasswordAuthenticationFilter.class);
        http.csrf().disable();
    }
}

5.验证:

在这里插入图片描述
在这里插入图片描述

6:项目完整代码:

gitee:https://gitee.com/wangdaxia0089/spring-security-demo

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/797826.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Flink集群运行模式--Standalone运行模式

Flink集群运行模式--Standalone运行模式 一、实验目的二、实验内容三、实验原理四、实验环境五、实验步骤5.1 部署模式5.1.1 会话模式&#xff08;Session Mode&#xff09;5.1.2 单作业模式&#xff08;Per-Job Mode&#xff09;5.1.3 应用模式&#xff08;Application Mode&a…

三层交换机实现DHCP功能

典型操作&#xff1a;三层交换机VLAN实现网络 可以实现基本的企业需求 华为的三层交换机实现DHCP功能&#xff0c;需要给vlan划分地址池 1.网络拓扑图 2.三层交换机的配置 //三层交换机的配置 //配置IP地址池&#xff0c;实现DHCP时分配给vlan下的终端 [Huawei]ip pool vl…

玩转smardaten | 零基础构建多维数据可视化大屏(最全攻略)

不要再问睿睿&#xff1a;数据可视化大屏怎么做啦&#xff01; 没学过任何编程代码怎么办&#xff0c;能做吗&#xff1f;根本不是问题&#xff01; 这篇文章手把手教你&#xff0c;全方位攻略smardaten数据可视化大屏&#xff08;搭建无需代码&#xff09;~~ 一、可视化大屏…

TSINGSEE青犀视频汇聚融合平台EasyCVR的中性化版本如何配置?

TSINGSEE青犀视频监控管理平台EasyCVR能在复杂的网络环境中&#xff0c;将分散的各类视频资源进行统一汇聚、整合、集中管理&#xff0c;实现视频资源的鉴权管理、按需调阅、全网分发、智能分析等&#xff0c;平台融合性强、开放度高、部署轻快&#xff0c;在智慧工地、智慧园区…

tcpdump 抓包记录

查看发往 10.0.2.220 的包 [rootbigdata-storage-05 ~]# tcpdump -i any -nn dst 10.0.2.220 tcpdump: verbose output suppressed, use -v or -vv for full protocol decode listening on any, link-type LINUX_SLL (Linux cooked), capture size 262144 bytes 16:40:55.0253…

github token使用方法

git remote set-url origin https://<githubtoken>github.com/<username>/<repositoryname>.git 在私有仓库的HTTPS的url上加入<githubtoken>即为token url&#xff0c;可以免ssh key登录

入局元宇宙,所谓的无限可能到底在哪里?

最近的热点新闻表明&#xff0c;人们似乎认为元宇宙已经走向“死亡”。但实际上&#xff0c;市场应该重新定义对元宇宙的看法&#xff0c;以及正视它最大的机会所在——游戏领域。 1937年5月6日&#xff0c;一架名为兴登堡号的巨大氢能齐柏林飞艇飞临新泽西州曼彻斯特镇上空&a…

Dubbo 指定调用固定ip+port dubbo调用指定服务 dubbo调用不随机 dubbo自定义调用服务 dubbo点对点通信 dubbo指定ip

1. 在写分布式im时nami-im: 分布式im, 集群 zookeeper netty kafka nacos rpc主要为gate&#xff08;长连接服务&#xff09; logic &#xff08;业务&#xff09; lsb &#xff08;负载均衡&#xff09;store&#xff08;存储&#xff09; - Gitee.com&#xff0c;需要指定某一…

本地缓存LoadingCache

引入依赖 <!-- https://mvnrepository.com/artifact/com.google.guava/guava --> <dependency><groupId>com.google.guava</groupId><artifactId>guava</artifactId><version>32.1.1-jre</version> </dependency>主要代…

可以进行ai图片生成的三款软件分享给你

现在人类社会进入了一个令人瞩目的科技时代。人工智能已经渗透到生活的方方面面&#xff0c;然而&#xff0c;在这个智慧的时代&#xff0c;一种特殊的ai技术吸引着全球的目光&#xff0c;那就是ai自动生成图片软件&#xff0c;人们运用这种技术生成了下面这些美丽的图片。但同…

Docker构建Java镜像并部署Java项目

文章目录 1. 准备工作2. 创建Dockerfile3. 构建镜像4. 查看镜像是否构建成功5. 运行容器6. 访问Java服务7. 总结 本文介绍了如何使用Docker构建一个Java项目的镜像&#xff0c;并以后端项目为例进行演示。在这个例子中&#xff0c;我们将使用eclipse-temurin:8-jre作为基础镜像…

光伏圈告别「看天吃饭」,塞浦路斯大学耗时 2 年,发现机器学习预测污染损失未来可期

内容一览&#xff1a;光伏系统是一种利用太阳能发电的可再生能源解决方案&#xff0c;具有减少温室气体排放、分散式发电、经济效益等优势&#xff0c;对于推动可持续能源发展和应对环境挑战具有重要作用。然而&#xff0c;许多具有最高太阳辐射的地点也存在地面干燥、多尘的缺…

Vue2基础九、路由

零、文章目录 Vue2基础九、路由 1、单页应用 &#xff08;1&#xff09;单页应用是什么 单页面应用(SPA&#xff1a;Single Page Application): 所有功能在 一个html页面 上实现具体示例: 网易云音乐 https://music.163.com/ &#xff08;2&#xff09;单页面应用VS多页面…

角色权限的设置

1.先在登录页把角色存起来 2.然后分成普通管理员路由和超级管理员路由的动态路由 3.在导航栏这边接收循环路由以及文字等 4.给路由加属性看是否展示在导航栏ismenu 5.在templat标签上面循环 <template><div class"asders"><el-aside width"200…

Mybatis-Flex

一、Mybatis-Flex是什么&#xff1f; Mybatis-Flex 是一个优雅的 Mybatis 增强框架&#xff0c;它非常轻量、同时拥有极高的性能与灵活性。我们可以轻松的使用 Mybaits-Flex 链接任何数据库&#xff0c;其内置的 QueryWrapper^亮点 帮助我们极大的减少了 SQL 编写的工作的同时…

mfc140.dll丢失的多种解决方法分享,最全面的mfc140.dll文件修复手法

其实想要修复丢失的mfc140.dll文件&#xff0c;还是非常的简单的&#xff0c;我们需要针对其丢失的原因&#xff0c;去做针对性的修复&#xff0c;并不是所有的修复手段都是有用的&#xff01;这点我们必须了解清楚&#xff0c;好了下面我们一起来了解一下mfc140.dll丢失的多种…

神码ai火车头伪原创插件怎么用【php源码】

大家好&#xff0c;本文将围绕python绘制烟花特定爆炸效果展开说明&#xff0c;如何用python画一朵花是一个很多人都想弄明白的事情&#xff0c;想搞清楚用python画烟花的代码需要先了解以下几个事情。 1、表白烟花代码 天天敲代码的朋友&#xff0c;有没有想过代码也可以变得…

SSH连接Windows「用户名与密码的坑」及解决方案

文章目录 问题方案 问题 当我们想要通过 SSH 连接 Windows 来进行一些远程办公的时候&#xff0c;通常需要进行以下准备工作&#xff1a; 在 Windows 上安装 OpenSSH 服务器 在系统的「设置>应用>可选功能」中搜索关键词「SSH」即可找到该应用并下载安装 确定 Windows…

java:匿名内部类

匿名内部类 匿名内部类一般作为一个参数传递给方法 首先不作为参数 同时可以让代码更简化&#xff0c;直接调用go方法&#xff0c;将S1替换&#xff0c;也就是将内部类直接作为参数&#xff0c;传递给方法 内部类不是主动去实现而是被动实现的

Zabbix下载安装过程中的报错问题与解决方案

目录 系统环境1. switch-to 指令错误2. 缺少的组或模块 : php:7.4 / perl:5.26&#xff0c;以及衍生出来的一系列依赖模块缺少的问题3. 初始化架构和数据时缺失server.sql.gz&#xff0c;无法正常导入4. 启动Zabbix server和agent进程时无法正常启动&#xff0c;但也没有其他问…