Shiro安全框架与SpringBoot的整合(下)

目录

一、整合前的配置

1.1 导入shiro依赖

1.2 config配置

1.2.1 ShiroConfig(⭐)

 1.2.2 MyConfig(拦截器配置)

 3. 拦截器(LoginInterceptor)

二、认证登录

2.1. controller

2.2 service和serviceImpl(不用)

2.3 mapper

2.4 自定义的shiro和realm

三、权限授权验证

3.1. controller(测试接口的权限)

3.2 自定义的shiro和realm

四、动态菜单的实现

4.1 目标效果

4.2  查询所有的权限

4.3 不同的用户显示不同的菜单(权限)


一、整合前的配置

1.1 导入shiro依赖

        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-core</artifactId>
            <version>1.3.2</version>
        </dependency>
        <dependency>
            <groupId>commons-logging</groupId>
            <artifactId>commons-logging</artifactId>
            <version>1.2</version>
        </dependency>
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-spring</artifactId>
            <version>1.3.2</version>
        </dependency>

1.2 config配置

1.2.1 ShiroConfig(⭐)

配置shiro的一些基本配置,需要注意--设置安全管理器securityManager与你的项目有关,

这里我设置了登录时需要的自定义myRealm,和权限授权验证前的自定义uuidRealm。

package com.itqq.config;

import com.itqq.realm.MyRealm;
import com.itqq.realm.UUIDRealm;
import org.apache.shiro.realm.Realm;
import org.apache.shiro.spring.LifecycleBeanPostProcessor;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;

import java.util.ArrayList;
import java.util.List;

/**
 * Created with IntelliJ IDEA.
 *
 * @Author: sys
 * @Description:shiro整合Spring的配置文件
 */
@Configuration
public class ShiroConfig {
    @Autowired
    private MyRealm myRealm;
    @Autowired
    private UUIDRealm uuidRealm;

    @Bean
    @DependsOn("lifecycleBeanPostProcessor")
    public DefaultAdvisorAutoProxyCreator getDefaultAdvisorAutoProxyCreator() {
        DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
        defaultAdvisorAutoProxyCreator.setProxyTargetClass(true);
        return defaultAdvisorAutoProxyCreator;
    }
    @Bean(name = "lifecycleBeanPostProcessor")
    public static LifecycleBeanPostProcessor getLifecycleBeanPostProcessor() {
        return new LifecycleBeanPostProcessor();
    }
    @Bean
    public AuthorizationAttributeSourceAdvisor getAuthorizationAttributeSourceAdvisor() {
        AuthorizationAttributeSourceAdvisor aasa = new AuthorizationAttributeSourceAdvisor();
        aasa.setSecurityManager(securityManager());
        return new AuthorizationAttributeSourceAdvisor();
    }
    // 设置安全管理器securityManager
    @Bean
    public DefaultWebSecurityManager securityManager() {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        List<Realm> realms = new ArrayList<>();
        realms.add(myRealm);
        realms.add(uuidRealm);
        securityManager.setRealms(realms);
        return securityManager;
    }
    // 设置filter
    @Bean
    public ShiroFilterFactoryBean shiroFilterFactoryBean(){
        ShiroFilterFactoryBean shiroFilter = new ShiroFilterFactoryBean();
        shiroFilter.setSecurityManager( securityManager());
        shiroFilter.setLoginUrl("/anon");
        shiroFilter.setUnauthorizedUrl("/anon");
        return shiroFilter;
    }
//    @Bean
//    public MyRealm myRealm(){
//        return new MyRealm();
//    }
}
 1.2.2 MyConfig(拦截器配置)

因为每次权限验证前都需要验证该账号是否登录,所以使用拦截器

package com.itqq.config;

import com.itqq.interceptor.LoginInterceptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

/**
 * Created with IntelliJ IDEA.
 *
 * @Author: syq
 * @Description:
 */
@Configuration
public class MyConfig implements WebMvcConfigurer {
    @Autowired
    private LoginInterceptor loginInterceptor;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
//        将loginInterceptor这个拦截器注册到Spring Boot中,并排除对/employee/login(登录)这个路径的拦截
        registry.addInterceptor(loginInterceptor).excludePathPatterns("/employee/login");
    }
}

 3. 拦截器(LoginInterceptor)

将重复的代码抽取出来,此时,用户已经登录过一次,需要再次认证

package com.itqq.interceptor;

import com.itqq.shiro.UUIDToken;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.subject.Subject;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * Created with IntelliJ IDEA.
 *
 * @Author: syq
 * @Description:使用过滤器用户在进行权限验证时必须要先认证,一个个加太麻烦
 * 所以在拦截器中统一进行认证
 *
 */
@Component
public class LoginInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        try {
            String token = request.getHeader("token");
//            使用Shiro框架的SecurityUtils.getSubject()方法获取当前的Subject(即用户身份)
            Subject subject = SecurityUtils.getSubject();
//            将token传给UUIDRealm进行认证
            subject.login(new UUIDToken(token));
        }catch (Exception e){
            e.printStackTrace();
        }
        return true;
    }
}

二、认证登录

使用shiro框架自带的组件进行登录验证,不用用户的service和serviceImpl

2.1. controller

package com.itqq.controller;

import com.itqq.pojo.Employee;
import com.itqq.pojo.Result;
import com.itqq.service.EmployeeService;
import com.itqq.shiro.PhonePasswordToken;
import org.apache.shiro.SecurityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.*;

import java.util.UUID;

/**
 * Created with IntelliJ IDEA.
 *
 * @Author: syq
 * @Description:
 */
@RestController
@RequestMapping("employee")
public class EmployeeController {
    @Autowired
    private EmployeeService employeeService;
    @Autowired
    private RedisTemplate redisTemplate;
    /**
     * 登录接口
     * @param token
     * @return
     */
    @PostMapping("login")
    public Result login(@RequestBody PhonePasswordToken token) {
//        此token是前端传来的登录信息,这里是phone和password
        SecurityUtils.getSubject().login(token);
        String tokenString = UUID.randomUUID().toString().replace("-", "");
        redisTemplate.opsForValue().set(tokenString, SecurityUtils.getSubject().getPrincipal());
        return Result.success(tokenString);
    }
    @GetMapping("")
    public Result findAll() {
        return Result.success(employeeService.findAll());
    }
    @GetMapping("findById/{id}")
    public Result findById(@PathVariable Integer id) {
        return Result.success(employeeService.findById(id));
    }
    /**
     * 添加员工
     * @param employee
     * @return
     */
    @PostMapping("add")
    public Result add(@RequestBody Employee employee) {
        return employeeService.add(employee) ? Result.success("添加成功") : Result.failed("添加失败");
    }
    @PostMapping("update")
    public Result update(@RequestBody Employee employee) {
        return employeeService.update(employee) ? Result.success("修改成功") : Result.failed("修改失败");
    }
    @DeleteMapping("delete")
    public Result delete(Integer id) {
        return employeeService.delete(id) ? Result.success("删除成功") : Result.failed("删除失败");
    }
    @DeleteMapping("deleteids")
    public Result deleteids(Integer[] ids) {
        return employeeService.deleteids(ids) ? Result.success("删除成功") : Result.failed("删除失败");
    }
}

2.2 service和serviceImpl(不用)

package com.itqq.service;

import com.itqq.pojo.Employee;
import com.itqq.pojo.Result;

import java.util.List;

/**
 * Created with IntelliJ IDEA.
 *
 * @Author: syq
 * @Description:
 */
public interface EmployeeService {

    List<Employee> findAll();

    Employee findById(Integer id);

    boolean add(Employee employee);

    boolean update(Employee employee);

    boolean delete(Integer id);

    boolean deleteids(Integer[] ids);

    Employee findEmployeeByName(String name);

    Employee findEmployeeByPhone(Long phone);
}

增加用户信息的时候,密码进行MD5加密 ,盐是动态盐

package com.itqq.service.impl;


import com.itqq.mapper.EmployeeMapper;
import com.itqq.pojo.Employee;
import com.itqq.service.EmployeeService;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.crypto.hash.SimpleHash;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

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

/**
 * Created with IntelliJ IDEA.
 *
 * @Author: syq
 * @Description:
 */
@Service
public class EmployeeServiceImpl implements EmployeeService {
    @Autowired
    private EmployeeMapper employeeMapper;

    @Override
    public List<Employee> findAll() {
        return employeeMapper.findAll();
    }

    @Override
    public Employee findById(Integer id) {
        return employeeMapper.findById(id);
    }

    @Override
    public boolean add(Employee employee) {
//      添加的时候设置动态盐
        String slat = UUID.randomUUID().toString().replace("-", "");
//        密码加密存储
        String password = String.valueOf(new SimpleHash("MD5", employee.getPassword(), slat, 1024));
//        获取当前登录人的id
        Integer principal = (Integer) SecurityUtils.getSubject().getPrincipal();
        employee.setPassword(password);
        employee.setSalt(slat);
        employee.setCreateTime(new Date());
        employee.setCreateId(principal);
        return employeeMapper.add(employee);
    }

    @Override
    public boolean update(Employee employee) {
        return employeeMapper.update(employee);
    }

    @Override
    public boolean delete(Integer id) {
        return employeeMapper.delete(id);
    }

    @Override
    public boolean deleteids(Integer[] ids) {
        return employeeMapper.deleteids(ids);
    }

    @Override
    public Employee findEmployeeByName(String name) {
        return employeeMapper.findEmployeeByName(name);
    }

    @Override
    public Employee findEmployeeByPhone(Long phone) {
        return employeeMapper.findEmployeeByPhone(phone);
    }
}

2.3 mapper

package com.itqq.mapper;

import com.itqq.pojo.Employee;
import org.apache.ibatis.annotations.Mapper;

import java.util.List;

/**
 * Created with IntelliJ IDEA.
 *
 * @Author: syq
 * @Description:
 */
public interface EmployeeMapper {
    List<Employee> findAll();

    Employee findById(Integer id);

    boolean add(Employee employee);

    boolean update(Employee employee);

    boolean delete(Integer id);

    boolean deleteids(Integer[] ids);

    Employee findEmployeeByName(String name);

    Employee findEmployeeByPhone(Long phone);
}
<?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.itqq.mapper.EmployeeMapper">
    <insert id="add">
        insert into sys_employee(name,password,phone,salt,status,create_id,create_time)
        values(#{name},#{password},#{phone},#{salt},#{status},#{createId},#{createTime})
    </insert>
    <update id="update">
        update sys_employee
        <set>
            <if test="name != null">
                name = #{name},
            </if>
            <if test="password != null">
                password = #{password},
            </if>
            <if test="phone != null">
                phone = #{phone},
            </if>
            <if test="salt != null">
                salt = #{salt},
            </if>
            <if test="status != null">
                status = #{status},
           </if>
            <if test="createId != null">
                create_id = #{createId},
            </if>
            <if test="createTime != null">
                create_time = #{createTime},
            </if>
        </set>
    </update>
    <delete id="delete">
        delete from sys_employee where id = #{id}
    </delete>
    <delete id="deleteids">
        delete from sys_employee where id in
        <foreach collection="ids" item="id" open="(" separator="," close=")">
            #{id}
        </foreach>
    </delete>
    <select id="findAll" resultType="com.itqq.pojo.Employee">
        select * from sys_employee
    </select>
    <select id="findById" resultType="com.itqq.pojo.Employee">
        select * from sys_employee where id = #{id}
    </select>
    <select id="findEmployeeByName" resultType="com.itqq.pojo.Employee">
        select * from sys_employee where name = #{name}
    </select>
    <select id="findEmployeeByPhone" resultType="com.itqq.pojo.Employee">
        select * from sys_employee where phone = #{phone}
    </select>
</mapper>

2.4 自定义的shiro和realm

package com.itqq.realm;

import com.itqq.pojo.Employee;
import com.itqq.service.EmployeeService;
import com.itqq.shiro.PhonePasswordToken;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

/**
 * Created with IntelliJ IDEA.
 *
 * @Author: syq
 * @Description:自定义的MyRealm用于认证使用
 */
@Component
public class MyRealm extends AuthorizingRealm {
    @Autowired
    private EmployeeService employeeService;
    public MyRealm() {
        HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
        hashedCredentialsMatcher.setHashAlgorithmName("MD5");
        hashedCredentialsMatcher.setHashIterations(1024);
        this.setCredentialsMatcher(hashedCredentialsMatcher);
    }
//    判断传入的AuthenticationToken对象是否是PhonePasswordToken类型的实例
    @Override
    public boolean supports(AuthenticationToken token) {
        return token instanceof PhonePasswordToken;
    }

    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        return null;
    }
//    认证
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        System.out.println("-----------------开始认证!!!!");
//        接收用户输入的账号(手机号)和密码
        Long phone = (Long) token.getPrincipal();
        String password = (String) token.getCredentials();
        if(phone == null){
            throw new AuthenticationException("账号不能为空");
        }
        if(!StringUtils.hasText(password)){
            throw new AuthenticationException("密码不能为空");
        }
//        从数据库中查询对象
        Employee employee = employeeService.findEmployeeByPhone(phone);
        if(employee == null){
            throw new AuthenticationException("用户名不存在");
        }
        System.out.println(employee.getSalt());
        System.out.println(employee.getName());
        System.out.println(employee.getPassword());
        return new SimpleAuthenticationInfo(employee.getId(),employee.getPassword(),ByteSource.Util.bytes(employee.getSalt()),getName());
    }
}

自定义的shiro组件接收 前端传来的登录信息

package com.itqq.shiro;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.apache.shiro.authc.AuthenticationToken;

import java.io.Serializable;

/**
 * Created with IntelliJ IDEA.
 *
 * @Author: syq
 * @Description:
 */
@Data
@AllArgsConstructor
@NoArgsConstructor
public class PhonePasswordToken implements AuthenticationToken, Serializable {
    private static final long serialVersionUID = -240712713650948393L;
    private Long phone;
    private String password;

    @Override
    public Object getPrincipal() {
        return phone;
    }

    @Override
    public Object getCredentials() {
        return password;
    }
}

三、权限授权验证

认证之后,每次权限验证前需要再次进行登录验证(具体配置见config拦截器配置)

3.1. controller(测试接口的权限)

package com.itqq.controller;

import com.itqq.pojo.Result;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authz.annotation.Logical;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.apache.shiro.authz.annotation.RequiresRoles;
import org.apache.shiro.authz.annotation.RequiresUser;
import org.apache.shiro.subject.Subject;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * Created with IntelliJ IDEA.
 *
 * @Author:syq
 * @Description:授权测试
 */
@RestController
@RequestMapping("welcome")
public class WelcomeController {
     /*
        1. 游客接口
        2. 认证接口
        3. 游客/认证接口
        4. 授权接口
     */
     @GetMapping("1.do")
     public Result m1(){
         return Result.success("1.游客接口!!!");
     }
//    @RequiresUser需要用户认证才能访问的方法或类,要token
    @RequiresUser
    @GetMapping("2.do")
    public Result m2(/*@RequestHeader String token*/){
        Subject subject = SecurityUtils.getSubject();
//        subject.login(new UUIDToken(token));
        return Result.success("2.认证接口!!!" +  subject.getPrincipals());
    }
    @RequestMapping("3.do")
    public Result m3(){
        Subject subject = SecurityUtils.getSubject();
        if(subject.isAuthenticated()){
            return Result.success("3.认证接口!!!" + subject.getPrincipals());
        }else{
            return Result.failed("3.游客接口!!!");
        }
    }
//    @RequiresRoles注解,表示该接口需要在具有特定角色的用户才能访问
    @RequiresRoles("管理员")
    @RequestMapping("4.do")
    public Result m4(){
        Subject subject = SecurityUtils.getSubject();
        return Result.success("4-1.授权角色接口" +  subject.getPrincipals());
    }
    @RequiresPermissions("sys:employee:insert")
    @RequestMapping("5.do")
    public Result m5(){
        Subject subject = SecurityUtils.getSubject();
        return Result.success("5-2.授权权限接口" +  subject.getPrincipals());
    }
    //    @RequiresRoles({"管理员","管理员2"})--两个角色都要满足
    @RequiresRoles(value = {"管理员","超级管理员"},logical = Logical.OR)//只用满足一个条件
    @RequestMapping("6.do")
    public Result m6(){
        Subject subject = SecurityUtils.getSubject();
        return Result.success("6-2.授权权限接口" +  subject.getPrincipals());
    }
}

service和serviceImpl和上述一样这里就不在赘述 

3.2 自定义的shiro和realm

 将当前账号有关的角色信息和权限信息添加到shiro组件中,用于判断

package com.itqq.realm;

import com.itqq.mapper.PermissionMapper;
import com.itqq.service.EmployeeService;
import com.itqq.service.PermissionService;
import com.itqq.service.RoleService;
import com.itqq.shiro.UUIDToken;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

/**
 * Created with IntelliJ IDEA.
 *
 * @Author: syq
 * @Description:
 */
@Component
@Slf4j
public class UUIDRealm extends AuthorizingRealm {
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private RoleService roleService;
    @Autowired
    private PermissionService permissionService;

    //用于判断传入的AuthenticationToken对象是否是UUIDToken的实例。如果是,则返回true,表示支持该令牌;否则返回false,表示不支持该令牌。
    @Override
    public boolean supports(AuthenticationToken token) {
        return token instanceof UUIDToken;
    }
//    该函数调用了roleService.findRoleNameByEmployeeId(id)方法,
//    将返回值添加到info对象的roles属性中。
//    findRoleNameByEmployeeId方法根据员工ID查找对应的职位名称
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        Integer id = (Integer) principalCollection.getPrimaryPrincipal();
        log.info("id:{}",id);
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        info.addRoles(roleService.findRoleNameByEmployeeId(id));
        info.addStringPermissions(permissionService.findPermissionNameByEmployeeId(id));
        return info;
    }

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
//          从令牌中提取UUID作为凭证
        String uuid = (String) token.getCredentials();
        if(!StringUtils.hasText(uuid)){
            throw new RuntimeException("token不能为空");
        }
//        从resdis中获取员工id
        Integer id = (Integer)redisTemplate.opsForValue().get(uuid);
        if(id == null){
            throw new RuntimeException("token已经失效");
        }
//        构建认证信息对象,包含用户ID、UUID和名称
//        将员工id,uuid(生成的),名称送去校验
        return new SimpleAuthenticationInfo(id,uuid,getName());
    }
}
package com.itqq.shiro;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.apache.shiro.authc.AuthenticationToken;

import java.io.Serializable;

/**
 * Created with IntelliJ IDEA.
 *
 * @Author: syq
 * @Description:
 */
@Data
@AllArgsConstructor
@NoArgsConstructor
public class UUIDToken implements AuthenticationToken, Serializable {
    private static final long serialVersionUID = 8884806189738587998L;
    private String uuid;
    @Override
    public Object getPrincipal() {
        return uuid;
    }

    @Override
    public Object getCredentials() {
        return uuid;
    }
}

四、动态菜单的实现

4.1 目标效果

 

 数据库设计

动态菜单需要根据查看用户的所有权限,主要是要进行树状显示查询

4.2  查询所有的权限

1. Controller


//    查询全部数据
    List<Permission> findByParentId(Integer id);

2. service和serviceImpl

    List<Permission> findAll();
    public List<Permission> findAll() {
        return permissionMapper.findByParentId(0);
    }

3. mapper

//    查询全部数据
    List<Permission> findByParentId(Integer id);

先运行findByParentId,运行一次后,结果映射又递归调用此时将id赋值parentId 

 <resultMap id="permission" type="Permission">
        <id column="id" property="id"/>
        <result column="name" property="name"/>
        <result column="path" property="path"/>
        <result column="permission" property="permission"/>
        <result column="icon" property="icon"/>
        <result column="parent_id" property="parentId"/>
        <result column="create_id" property="createId"/>
        <result column="create_time" property="createTime"/>
        <result column="index" property="index"/>
        <collection property="children" ofType="Permission" select="findByParentId" column="id"></collection>
    </resultMap>
    <select id="findByParentId" resultMap="permission">
        select * from sys_permission where parent_id = #{parentId}
    </select>

4.3 不同的用户显示不同的菜单(权限)

1. controller

//    获取当前用户的菜单
    @RequiresUser
    @GetMapping("menu")
    public Result findMenu(){
        return Result.success(permissionService.findMenu());
    }

2. service和serviceImpl

List<Permission> findMenu(
public List<Permission> findMenu() {
        Integer eid = (Integer) SecurityUtils.getSubject().getPrincipal();
        return permissionMapper.findMenu(eid, 0);
    }

3. mapper

//    根据不同的用户查询数据
    List<Permission> findMenu(@Param("eid") Integer eid,@Param("parentId") Integer parentId);
<resultMap id="permission1" type="Permission">
        <id column="id" property="id"/>
        <result column="name" property="name"/>
        <result column="path" property="path"/>
        <result column="permission" property="permission"/>
        <result column="icon" property="icon"/>
        <result column="parent_id" property="parentId"/>
        <result column="create_id" property="createId"/>
        <result column="create_time" property="createTime"/>
        <result column="index" property="index"/>
        <collection property="children" ofType="Permission" select="findMenu" column="{eid=eid,parentId=id}"></collection>
    </resultMap>
    <select id="findMenu" resultMap="permission1">
        SELECT DISTINCT p.*,eid from sys_permission p
                                LEFT JOIN sys_role_permission rp on p.id = rp.pid
                                LEFT JOIN sys_employee_role er on er.rid = rp.rid
        where eid = #{eid} and parent_id = #{parentId} and permission is null
        order by p.index asc
    </select>

4. pojo

@Data
public class Permission implements Serializable {
    private static final long serialVersionUID = -9189388242103298381L;
    private Integer id;
    private String name;
    private String permission;
    private String path;
    private String icon;
    private Integer parentId;
    private Integer createId;
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
    private Timestamp createTime;
    private Integer index;

    private List<Permission> children;
}

总结完毕!!!

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值