自己开发完整项目一、登录功能-03(使用springSecurity安全框架,查询用户角色权限)

news2024/12/23 9:12:36

一、说明

在前面两章节,实现了通过springsecurity来进行用的登录认证,当用户输入用户名和密码之后,通过额数据库中的信息比对,比对成功那么放行。但是还存在一个问题:因为系统的所有页面包括按钮都是有各自的权限,那么要想实现不同的用户登录成功看到的页面不同并且有不同的操作范围,那么就需要对用户的权限进行验证。

实现的思路:在用户登录的时候,将用户的权限查询出来。

二、具体实现

1、创建roleModel

package com.ljy.myspringbootlogin.model;

import com.baomidou.mybatisplus.annotation.*;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;

import java.io.Serializable;
import java.util.List;


@TableName("role")
public class RoleModel implements Serializable {

    /**
     * id
     */
    @TableId(type = IdType.AUTO)
    private Long id;

    /**
     * 角色名称
     */
    @TableField("role_name")
    private String roleName;

    /**
     * 角色标签
     */
    @TableField("role_tag")
    private String roleTag;

    /**
     * 是否删除
     */
    @TableField("is_deleted")
    private Long isDeleted;





    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getRoleName() {
        return roleName;
    }

    public void setRoleName(String roleName) {
        this.roleName = roleName;
    }

    public String getRoleTag() {
        return roleTag;
    }

    public void setRoleTag(String roleTag) {
        this.roleTag = roleTag;
    }

    public Long getIsDeleted() {
        return isDeleted;
    }

    public void setIsDeleted(Long isDeleted) {
        this.isDeleted = isDeleted;
    }
}

2、创建menuModel

package com.ljy.myspringbootlogin.model;

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;

import java.io.Serializable;
import java.util.List;


@TableName("menu")
public class MenuModel implements Serializable {

    /**
     * id
     */
    @TableId(type = IdType.AUTO)
    private Long id;

    /**
     * 权限名称
     */
    @TableField("menu_name")
    private String menuName;

    /**
     * 权限标签
     */
    @TableField("menu_tag")
    private String menuTag;

    /**
     * 是否删除
     */
    @TableField("is_deleted")
    private Long isDeleted;

    /**
     * 权限父id
     */
    @TableField("parent_id")
    private Long partendId;

    /**
     * 权限类型
     */
    @TableField("menu_type")
    private Long menuType;

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getMenuName() {
        return menuName;
    }

    public void setMenuName(String menuName) {
        this.menuName = menuName;
    }

    public String getMenuTag() {
        return menuTag;
    }

    public void setMenuTag(String menuTag) {
        this.menuTag = menuTag;
    }

    public Long getIsDeleted() {
        return isDeleted;
    }

    public void setIsDeleted(Long isDeleted) {
        this.isDeleted = isDeleted;
    }

    public Long getPartendId() {
        return partendId;
    }

    public void setPartendId(Long partendId) {
        this.partendId = partendId;
    }

    public Long getMenuType() {
        return menuType;
    }

    public void setMenuType(Long menuType) {
        this.menuType = menuType;
    }
}

3、修改userModel

我们需要将用户的权限返回,而在springsecurity中,必须返回一个集成了userDetails的用户,所以我们为了方便,将角色信息和权限信息全部的返回到UserModel中。

package com.example.springsecurity03.model;

import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;

import java.util.Collection;
import java.util.List;

/**
 * 用户
 */
//当使用springsecurity做为安全框架的时候,用户model必须实现UserDetails,因为springsecuritty会使用UserDetails里面的权限信息和账号密码等信息
//进行认证和授权

public class UserModel implements UserDetails {
    //id
    private Long id;

    //用户名
    private String username;

    //密码
    private String password;

    //权限
    private Collection<GrantedAuthority>  authorities;

    //是否锁定
    private boolean enabled;

    public void setEnabled(boolean enabled) {
        this.enabled = enabled;
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    @Override
    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

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

    public void setPassword(String password) {
        this.password = password;
    }

    @Override
    public Collection<GrantedAuthority> getAuthorities() {
        return authorities;
    }

    public void setAuthorities(Collection<GrantedAuthority> authorities) {
        this.authorities = authorities;
    }

    /**
     * 判断账号是否未过期
     * @return
     */
    @Override
    public boolean isAccountNonExpired() {
        return true;
    }

    /**
     *判断账号是否未被锁定
     * @return
     */
    @Override
    public boolean isAccountNonLocked() {
        return true;
    }

    /**
     * 判断密码是否未过期
     * @return
     */
    @Override
    public boolean isCredentialsNonExpired() {
        return true;
    }

    /**
     * 判断账号是否启用
     * @return
     */
    @Override
    public boolean isEnabled() {
        return enabled;
    }
}

 4、创建roleService

因为我们需要通过用户的id去查询角色的信息,所以我们需要在roleService中编写一个查询角色信息的接口,方便后续调用。

package com.ljy.myspringbootlogin.service;

import com.baomidou.mybatisplus.extension.service.IService;
import com.ljy.myspringbootlogin.commont.Reuslt;
import com.ljy.myspringbootlogin.model.RoleModel;
import com.ljy.myspringbootlogin.model.UserModel;
import org.apache.ibatis.annotations.Param;

import java.util.List;

public interface IRoleService extends IService<RoleModel> {

    /**
     * 根据用户id查询角色信息
     */
    List<RoleModel> getRoleByUserId(@Param("userId") Long userId);
}

 5、创建roleServieImpl

package com.ljy.myspringbootlogin.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ljy.myspringbootlogin.commont.Reuslt;
import com.ljy.myspringbootlogin.mapper.RoleMapper;
import com.ljy.myspringbootlogin.mapper.UserMapper;
import com.ljy.myspringbootlogin.model.RoleModel;
import com.ljy.myspringbootlogin.model.UserModel;
import com.ljy.myspringbootlogin.service.IRoleService;
import com.ljy.myspringbootlogin.service.IUserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.UUID;

@Service
@Slf4j
public class RoleServiceImpl extends ServiceImpl<RoleMapper, RoleModel> implements IRoleService {

    @Autowired
    RoleMapper roleMapper;
    @Override
    public List<RoleModel> getRoleByUserId(Long userId) {
        List<RoleModel> roleByUserId = roleMapper.getRoleByUserId(userId);
        return roleByUserId;
    }
}

6、创建roleMapper

package com.ljy.myspringbootlogin.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.ljy.myspringbootlogin.model.RoleModel;
import com.ljy.myspringbootlogin.model.UserModel;
import org.apache.ibatis.annotations.Mapper;

import java.util.List;

@Mapper
public interface RoleMapper extends BaseMapper<RoleModel> {
    List<RoleModel> getRoleByUserId(Long userId);
}

7、创建roleMapper.xml

<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.ljy.myspringbootlogin.mapper.RoleMapper">
    <select id="getRoleByUserId" resultType="com.ljy.myspringbootlogin.model.RoleModel">
        select a.*
        from role a
        left join user_role b on a.id=b.role_id
        where b.user_id=#{userId}
    </select>

</mapper>

8、创建menuService

上面创建了通过用户id查询角色的接口,那么现在创建通过角色id查询权限的接口。

package com.ljy.myspringbootlogin.service;

import com.baomidou.mybatisplus.extension.service.IService;
import com.ljy.myspringbootlogin.model.MenuModel;
import com.ljy.myspringbootlogin.model.RoleModel;
import org.apache.ibatis.annotations.Param;

import java.util.List;

public interface IMenuService extends IService<MenuModel> {

    /**
     * 根据juese集合查询权限集合
     */
    List<MenuModel> getMenuByRoleIds(@Param("roleIds") List<Long> roleIds);

}

9、创建menuServiceImpl

package com.ljy.myspringbootlogin.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ljy.myspringbootlogin.mapper.MenuMapper;
import com.ljy.myspringbootlogin.model.MenuModel;
import com.ljy.myspringbootlogin.model.RoleModel;
import com.ljy.myspringbootlogin.service.IMenuService;
import com.ljy.myspringbootlogin.service.IRoleService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
@Slf4j
public class MenuServiceImpl extends ServiceImpl<MenuMapper, MenuModel> implements IMenuService {

    @Autowired
    MenuMapper menuMapper;
    @Override
    public List<MenuModel> getMenuByRoleIds(List<Long> roleIds) {
        List<MenuModel> menuByRoleIds = menuMapper.getMenuByRoleIds(roleIds);
        return menuByRoleIds;
    }
}

10、创建menuMapper

package com.ljy.myspringbootlogin.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.ljy.myspringbootlogin.model.MenuModel;
import com.ljy.myspringbootlogin.model.RoleModel;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;

import java.util.List;

@Mapper
public interface MenuMapper extends BaseMapper<MenuModel> {
    List<MenuModel> getMenuByRoleIds(@Param("roleIds") List<Long> roleIds);
}

11、创建menuMapper.xml

<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.ljy.myspringbootlogin.mapper.MenuMapper">
    <select id="getMenuByRoleIds" resultType="com.ljy.myspringbootlogin.model.MenuModel">
        select a.*
        from menu a
        left join role_menu b on a.id=b.menu_id
        where b.role_id in 
        <foreach collection="roleIds" open="(" close=")" separator="," item="roleId">
            #{roleId}
        </foreach>
    </select>

</mapper>

12、说明1

到此,通过用户id查询角色信息,通过角色id查询权限信息的两个接口都已经成功创建。接下来我们就需要在查询用户的接口处同时将角色信息和权限信息查询出来,并将角色信息放到userModel中的roleList中,将权限信息保存在userModel中的menuList中,注意:不管是roleList还是menuList,这两个都是我们自定义的属性,但是想要让springsecurity进行权限控制的话,我们必须将权限信息放到springsecurity中默认的权限属性中,也就是userModel中定义的private Collection<GrantedAuthority> authorities中,这个才是springsecurity提供的权限位置;。

13、修改查询用户信息的接口(springSecurityService.java)

package com.ljy.myspringbootlogin;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.ljy.myspringbootlogin.mapper.UserMapper;
import com.ljy.myspringbootlogin.model.MenuModel;
import com.ljy.myspringbootlogin.model.RoleModel;
import com.ljy.myspringbootlogin.model.UserModel;
import com.ljy.myspringbootlogin.service.IMenuService;
import com.ljy.myspringbootlogin.service.IRoleService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
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 java.util.ArrayList;
import java.util.Collection;
import java.util.List;

@Service
@Slf4j
public class springSecurityService implements UserDetailsService {
    @Autowired
    UserMapper userMapper;
    @Autowired
    IRoleService iRoleService;
    @Autowired
    IMenuService iMenuService;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        /**
         * 根据用户名查询用户
         */
        //通过账号查询用户
        System.out.println("进入!!!!");

//
        UserModel user = userMapper.getList(username);
        System.out.println("user:"+user.toString());
        //如果没有查询到用户,则抛出异常
        if(user == null){
            throw new UsernameNotFoundException("账号或密码错误!");
        }

        //TODO 后续可以查角色和权限
        //1.根据用户id查询出角色
        System.out.println("开始查询角色");
        List<RoleModel> roleByUserId = iRoleService.getRoleByUserId(user.getId());
        user.setRoleList(roleByUserId);
        System.out.println("角色查询完成");
        List<Long> roleIdList = new ArrayList<>();
        for (RoleModel roleModel : roleByUserId){
            roleIdList.add(roleModel.getId());
        }
        //2.根据角色id查询出权限

        System.out.println("开始查询权限");
        List<MenuModel> menuByRoleIds = iMenuService.getMenuByRoleIds(roleIdList);
        System.out.println("权限查询完成");
        user.setMenuList(menuByRoleIds);
        System.out.println("完成");

        //3.将权限信息放到springSecurity中
        List<String> roleSecurity = new ArrayList<>();
        for (MenuModel model : menuByRoleIds){
            roleSecurity.add(model.getMenuTag());
        }
        Collection<GrantedAuthority> grantedAuthorities = AuthorityUtils.createAuthorityList(roleSecurity.toArray(new String[0]));
        user.setAuthorities(grantedAuthorities);
        System.out.println("Authorities:"+user.getAuthorities());
        return user;
    }
}

14、到此查询用户的角色信息和权限信息功能完成,并将用户的权限信息返回给了springsecurity。执行查询返回效果

15、结束语句

这样写有一个问题,我们通过前端访问我们的系统,进行登录成功,进入到系统中,开始操作,那么上面的写法会存在一个问题,就是我们每次访问一个接口的时候,都需要重新登录,重新查询权限等等,这样不是预期效果,我们的预期效果是登录成功之后,在规定时间内,访问拥有权限的模块时候,是不需要每次都重新登录的,那么如何实现?就需要用到jwt来实现了,具体实现逻辑以及步骤在下篇文章进行记录。因为我还没有做到那里 哈哈哈哈哈

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

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

相关文章

全网最全robotframework自动化测试环境搭建

一、前言 1、在2019年之前&#xff0c;robotframework-ride的版本一直是1.5.2.1&#xff0c;是2016年1月份的版本&#xff0c;只能安装在python2.7的环境上&#xff0c;导致如果想同时使用robotframework做测试且又需要python3环境编写python代码的小伙伴都需要在操作系统上安…

Golang 读取文件

GoLang读取文件需要用到os类去打开文件&#xff0c;然后再用其他方式分析文件里的内容。打开文件比较简单&#xff0c;使用os.Open就可以了&#xff0c;记住用defer关闭就行。但是读取文件内容就头疼了&#xff0c;以文本文件为例子&#xff0c;就有各种方式 读取到byte数组 首…

渐进式衰老?医美三剑客的“市梦率”幻灭了

医美股神话彻底幻灭了。 从股价蒸发到业绩失速&#xff0c;“医美三剑客”上演着繁华落幕&#xff0c;回归平凡的剧本。 近一年来&#xff0c;爱美客、华熙生物、昊海生科股价分别累计下跌52.97%、46.03%、16.09%。 “医美三剑客”近一年累计跌幅&#xff08;资料来源&#x…

分水岭算法简介

分水岭算法是一种经典的图像分割技术&#xff0c;广泛应用于图像处理领域。它的名称源自地理学中的“分水岭”概念&#xff0c;即在地形中&#xff0c;水从高处流向低处&#xff0c;最终汇聚成河流的过程。在图像分割中&#xff0c;分水岭算法将灰度图像视为地形&#xff0c;将…

STM32(八):定时器——输入捕获实验

目录 输入捕获模式测频率&#xff1a; 结构图&#xff1a; 步骤&#xff1a; 部分函数详解&#xff1a; 源码&#xff1a; PWMI模式测频率占空比&#xff1a; 结构图&#xff1a; ​编辑 举例说明 源码&#xff1a; 输入捕获模式测频率&#xff1a; 结构图&#xf…

using showdown js with openAi streaming response

题意&#xff1a;"使用 Showdown.js 处理 OpenAI 流式响应" 问题背景&#xff1a; I tried using showdownjs to translate streamed markdown from OpenAi to HTML "我尝试使用 Showdown.js 将来自 OpenAI 的流式 Markdown 转换为 HTML" I changed the …

机器学习第五十四周周报 MAGNA

文章目录 week54 MAGNA摘要Abstract一、文献阅读1. 题目2. Abstract3. 文献解读3.1 Introduce3.2 创新点 4. MAGNA4.1 基础4.2 多跳注意力扩散机制4.3 网络架构4.4 图注意力扩散机制的分析 5. 实验分析5.1 节点分类5.2 知识图谱 6.结论 二、若依系统1. 权限管理2. 数据字典3. 其…

【Linux修行路】进程通信——共享内存

目录 ⛳️推荐 一、直接原理 1.1 共享内存的的申请 1.2 共享内存的释放 二、代码演示 2.1 shmget 2.1.1 详谈key——ftok 2.2 创建共享内存样例代码 2.3 获取共享内存——进一步封装 2.4 共享内存挂接——shmat 2.5 共享内存去关联——shmdt 2.6 释放共享内存——s…

gitee版本控制

前置要求&#xff1a; 安装Git git下载地址&#xff1a;https://git-scm.com/download/win 注册gitee gitee官网&#xff1a;Gitee - 基于 Git 的代码托管和研发协作平台 创建普通项目 目录 git推送远程仓库基本操作 克隆仓库到本地 项目上传 版本管理 分支管理版本…

紧急 浮毛正在挑战免疫系统?推荐榜TOP3浮毛空气净化器使用体验

作为一名多猫家庭的铲屎官&#xff0c;出门路人必知道我养猫&#xff0c;不是把铲屎官三个字大大的打在我脑门上了。而是衣服、裤子上无处不在的猫毛&#xff0c;以前我就靠着人力与各种工具与猫毛斗争&#xff0c;但效果总是差强人意。直到有一天&#xff0c;我因忽视浮毛而患…

Linux 用户缓冲区

1. 文件描述符的分配规则 我们知道Linux进程默认情况下会有3个缺省打开的文件描述符&#xff0c;分别是标准输入stdin--0&#xff0c; 标准输出stdout--1&#xff0c; 标准错误stderr--2。0,1,2对应的物理设备一般是&#xff1a;键盘&#xff0c;显示器&#xff0c;显示器.接下…

字符串原始字面量

简介&#xff1a;C11中添加定义了原始字符串的字面量&#xff0c;定义方式为&#xff1a;R"xxx(原始字符串)xxx",其中&#xff08;&#xff09;两边的字符串可以省略。原始字面量R可以直接表示字符串的实际含义&#xff0c;而不需要额外对字符串做转译或链接等操作 …

ddpm和ddim小记

前面分析了DDPM和DDIM&#xff0c;但是仍然感觉对其理解不是和透彻&#xff0c;最近又学习了下&#xff0c;简单记录一下进一步的理解。为了方便理解&#xff0c;这里直接以两个像素的灰度图像为例。前面讲过无论是DDPM还是DDIM&#xff0c;他们的训练过程都是一样的&#xff0…

一套采用JAVA语言开发的数字化产科管理平台源码,自主知识产权,三甲综合医院应用案例,系统稳定运行,全套源码交付。

一套采用JAVA语言开发的一套数字化产科管理平台源码&#xff0c;自主知识产权&#xff0c;三甲综合医院应用案例&#xff0c;系统稳定运行。全套源码交付。 数字化产科管理平台源码技术栈&#xff1a; 技术架构&#xff1a;前后端分离 开发语言&#xff1a;Java 开发工具…

深度学习基础--梯度下降与初始化

在神经网络的背景下&#xff0c;它们用于寻找能够最小化损失函数的参数&#xff0c;使模型能够根据输入准确预测训练数据的输出。基本方法是随机选择一组初始参数&#xff0c;然后逐步进行微小调整&#xff0c;平均而言这些调整会降低损失。每一次的调整都是基于当前参数位置对…

ERROR: Cannot uninstall numpy 1.24.2, RECORD file not found.

目录 1.问题描述&#xff1a;2.解决方法&#xff1a;2.1流程2.2结果 小结&#xff1a; 1.问题描述&#xff1a; 卸载 numpy 时报错&#xff1a; ERROR: Cannot uninstall numpy 1.24.2, RECORD file not found. You might be able to recover from this via: pip install --f…

HTB-sequal(mysql)

前言 各位师傅大家好&#xff0c;我是qmx_07&#xff0c;今天给大家讲解sequal这台靶机 渗透过程 信息搜集 服务器开放了3306mysql端口思路&#xff1a;mysql爆破-sC参数会执行 相关的默认脚本 连接mysql数据库 通过空密码连接道mysql数据库flag&#xff1a;7b4bec00d1a39…

【GD32】从零开始学GD32单片机 | USB通用串行总线接口+HID键盘例程(GD32F470ZGT6)

1. 简介 USB&#xff0c;全称通用串行总线&#xff0c;相信大家都非常熟悉了&#xff0c;日常生活只要用到手机电脑都离不开这个接口&#xff0c;像鼠标键盘U盘都需要使用这个接口进行数据传输&#xff0c;下面简单介绍一下。 1.1 版本标准 USB的标准总体可以分为低速、全速和…

04:布局规划

1.切换到丝印层 2.用2D线对模块区域划分

keil5烧录后不自动复位和Flash Download failed - “Cotex-M3“报错解决

目录 项目场景&#xff1a; 复位问题描述 复位原因分析&#xff1a; 复位解决方案&#xff1a; 下载错误问题描述 下载错误原因分析&#xff1a; 下载错误解决方案&#xff1a; 总结 项目场景&#xff1a; keil5编译stm32例程在烧录时候遇到的一些问题 复位问题描述 1. 使…