shiro - 前后端权限控制详细做法

16 篇文章 0 订阅
14 篇文章 0 订阅

之前的博文已经对shiro在springboot中的使用做了详细说明,这里继续说明如何具体实施,由于我一直在完善自已编写的博客,这里做一个笔记。

1. 创建表

我创建了4个表来对不同身份的用户进行权限管理,主要是通过用户->角色->权限进行管理
在这里插入图片描述
各个表的样子如下:
在这里插入图片描述

2. 定义Perm类

这里的类与之前创建的perm表相对应

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Perm implements Serializable {
    private Long permId;
    private String permission;
}

同时在User类中增加roleId属性
在这里插入图片描述

3.创建PermService进行管理

这里主要创建了两个方法

public interface PermService {
    //根据permId查询perm
    public Perm queryById(Long id);

    //根据username查询所有permission
    public List<Perm> queryByUserName(String username);

}

主要的对应的sql语句如下,相关的PermDao,PermServcieImpl这里就不再赘述:

<?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">
<!--查官网https://mybatis.org/mybatis-3/zh/getting-started.html-->
<!--映射到Dao文件-->
<mapper namespace="com.xinxin.dao.PermDao">
    <!--    开启二级缓存-->
    <cache />

    <select id="queryByUserName" parameterType="String" resultType="Perm">
    	<!--这里一次性连接了四个表-->
        SELECT permission FROM users,roles,role_perm,perms WHERE
            users.user_id = roles.role_id AND
            roles.role_id = role_perm.role_id AND
            role_perm.perm_id = perms.perm_id AND
            username= #{username}
    </select>

    <select id="queryById" resultType="Perm">
        select * from perms where perm_id = #{permId}
    </select>

</mapper>

4. 登录时直接获取权限

    @PostMapping("/api/login")
    public Object toLogin(@RequestBody JSONObject param) {
		
        //取出content
        String username = param.getString("username");
        String password=param.getString("password");
		
		
        //从SecurityUtils里边创建一个subject
        Subject subject = SecurityUtils.getSubject();
        //在认证提交前准备token(令牌)
        UsernamePasswordToken token = new UsernamePasswordToken(username, password);
        //自定义返加的token,登录后自动分配一个线程Id
        String token_res = subject.getSession().getId().toString();



        Map<String,Object> map=new HashMap<>();
        map.put("token",token_res);

        //获取权限List
        List<Perm> perms = permService.queryByUserName(username);

        if(perms.size()>0){
            //过滤掉Perm类中的permId  
            List<String> list = perms.stream().map(perm -> perm.getPermission()).distinct().collect(Collectors.toList());

            map.put("perm",list);
        }else{
            map.put("perm",null);
        }



        //执行shiro认证登陆,抛出的异常在GlobalExceptionHandler中处理
        subject.login(token);
        if (subject.isAuthenticated()) {
            return ApiResult.succ(map);

        } else {
            token.clear();
            return new ResponseEntity<>("登录失败", HttpStatus.NOT_FOUND);
        }


    }

关于shiro登录验证的操作,我之前的博客已经讲得非常详细,这里主要是将获取到的权限返回给前端。
通过Postman进行测试
在这里插入图片描述
可以看到成功取到了admin对应的权限。

5. 将权限保存在Vuex的state中

Vuex的操作方法见https://www.jianshu.com/p/a804606ad8e9,这里不再赘述。

5.1 让state持久化

我想把用户登录获得的权限保存在Vuex的state中,但是只要刷新页面,之前存入state中的数值就会消失,为了解决这个问题我参考了这位网友的做法,引入vuex-persistedstate插件

  1. 安装
npm install vuex-persistedstate --save
  1. store/index.js中将persistedstate引入
import Vue from "vue";
import Vuex from "vuex";
//引入vuex-persistedstate插件
import createPersistedState from "vuex-persistedstate"

Vue.use(Vuex);

export default new Vuex.Store({
  state: {
  	//测试初始值
    products: 'haha'
  },
  mutations: {
  	//通过调用minusPrice将state中products值替换为payload
    minusPrice (state, payload ) {
      state.products=payload
    }
  },
  actions: {},
  modules: {},
  //这里是将state持久化到localstorage,也就是本地
  plugins: [createPersistedState()]
});

在Vue页面中操作

//调用该命令改变state的值,将products改变为2
 this.$store.commit('minusPrice', 2);

//通过调用该命令直接获取state的值
this.msg=this.$store.state.products

5.2 测试

编写了一个测试页面验证刷新页面是否对state有影响,改变state之前:
在这里插入图片描述

点击按钮触发minusPrice()改变state为2
在这里插入图片描述
说明state已经持久化到了本地。

6.总结

这里将后端获取的用户权限持久化到了Vuex中的state中,就可以在任何一个页面取到state值,从而可以利用Vue中的v-if操作决定用户能够访问的页面元素了,这样前端与后端都实现了权限控制。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值