Java权限设计与控制

1.场景还原

    近期,由于项目中要引用权限模块,于是笔者趁着空暇时间写了一个权限控制的小Demo,现在跟大伙讲讲权限的原理。

2.权限数据库设计


user:用户表


user_role:用户角色表(用户跟角色多对多关系 )


role:角色表


role_permission:角色权限表(角色跟权限多对多关系)


permisssion:权限表


3.权限需求设计

该工程实现的需求:

1.通过用户id得到该用户的所有角色集合;

2.通过用户的角色得到该用户的所有权限;

3.通过角色id对该用户对应的角色权限进行增删操作;

4.对某用户拥有权限下的所有前端操作进行放行访问,反之拦截;

5.对某用户的角色类型进行判断

6.用户角色的赋予

7.用户角色的删除

4.准备工作

① springboot导入velocity模板

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-velocity</artifactId>
</dependency>
②配置velocity自动识别html
spring.velocity.suffix=.html

这样,springboot就会自动在src/main/resources/templates中寻找.html的文件;

③权限控制拦截器

public class PermissionInterceptor extends HandlerInterceptorAdapter {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //controller访问的相对路径
        String path=request.getServletPath();
        //取出session中的permission
        Set<String> permissionList = (Set<String>) request.getSession().getAttribute(SESSION_PERMISSION);
        if("/page/selectOne".equals(path)){
            if(permissionList.contains("user.select")){
                return true;
            }else{
                response.sendRedirect("error");
                return false;
            }

        }else if("/page/addOne".equals(path)){
            if(permissionList.contains("user.add")){
                return true;
            }else{
                response.sendRedirect("error");
                return false;
            }
        }else if("/page/updateOne".equals(path)){
            if(permissionList.contains("user.update")){
                return true;
            }else{
                response.sendRedirect("error");
                return false;
            }
        }else if("/page/deleteOne".equals(path)){
            if(permissionList.contains("user.delete")){
                return true;
            }else{
                response.sendRedirect("error");
                return false;
            }
        }else{
            return  true;
        }

    }
}

④注册该拦截器,使工程能够识别

@Configuration
public class CustomWebMvcConfigurerAdapter extends WebMvcConfigurerAdapter {
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        //拦截所有的controller
        registry.addInterceptor(new LoginInterceptor()).addPathPatterns("/**");
        registry.addInterceptor(new PermissionInterceptor()).addPathPatterns("/page/**");

    }
}

对page下的所有资源进行拦截,符合条件的放行,反之拦截抛出异常;

⑤前端通过控制相应的pageController进行页面跳转

/**
 * Created by zhangxing on 2017/6/13.
 */
@Controller
@CrossOrigin
public class PageController {

    @RequestMapping("/login")
    public String login(){
        return "hello";
    }

    @RequestMapping("/success")
    public String success(){
        return "first";
    }


    @RequestMapping("/quit")
    public String quit(){
        return "quit";
    }

    /**
     * 增加用户
     */
    @RequestMapping("/page/addOne")
    public String addOne(){
        return "add";
    }


    /**
     * 删除用户
     */
    @RequestMapping("/page/deleteOne")
    public String deleteOne(){
        return "delete";
    }

    /**
     * 查询用户
     */
    @RequestMapping("/page/selectOne")
    public String selectOne(){
        return "select";
    }


    /**
     * 查询用户
     */
    @RequestMapping("/page/updateOne")
    public String updateOne(){
        return "update";
    }

    /**
     * 用户注册
     */
    @RequestMapping("/page/submit")
    public String submit(){
        return "submit";
    }

    /**
     * 查询用户
     */
    @RequestMapping("/page/change")
    public String addPermission(){
        return "change";
    }

    /**
     * 更新权限
     */
    @RequestMapping("/page/flushPermission")
    public String flushPermission(){
        return "flush";
    }

    /**
     * 得到角色列表
     */
    @RequestMapping("/page/getRole")
    public String getRole(){
        return "flushRole";
    }
}
在前端调用以上PageController路径进行html页面跳转,例如:
window.location.href ="flushPermission";

5.具体实施步骤

①通过用户id得到该用户的所有角色集合

后台代码:

@GetMapping(value = "/getRoleId")
public Map<String,Object> getRoleId(Integer uid){
    List<Integer> rid = userService.getRoleId(uid);
    Map<String,Object> map = new HashMap<String, Object>();
    map.put("status",true);
    map.put("roleId",rid);
    return map;
}

②通过用户的角色得到该用户的所有权限

@GetMapping(value = "/getPermissionByRid")
public Map<String,Object> getPermissionByRid(Integer rid){
    Set<String> permission =  userService.getUserPermissionByRid(rid);

    Map<String,Object> map = new HashMap<String, Object>();
    map.put("newPermission",permission);
    map.put("change",true);
    return map;
}

登录成功后,对用户的角色进行遍历,获取该用户下的所有角色的权限集合

登录代码:

@GetMapping(value = "/login")
public Map<String,Object> getLogin(String loginName,String password){
    String zhangxing = Token.genetateToken();
    session.setAttribute(SESSION_TOKEN,zhangxing);
    //设置session的保质期为10s
    //session.setMaxInactiveInterval(10);
    //根据userId请求权限集合,将权限集合存入session
    int uid = userService.getUid(loginName);
    Set<String> permission =  userService.getUserAuth(uid);
    if(permission != null){
        session.setAttribute(SESSION_PERMISSION,permission);

    }
    List<Integer> rid = userService.getRoleId(uid);
    boolean login = false;
    String pwd = loginService.getPassword(loginName);
    Map<String,Object> map = new HashMap<String, Object>();
    if(pwd.equals(password)){
        login = true;
    }
    map.put("uid",uid);
    map.put("login",login);
    map.put("token",zhangxing);
    map.put("roleId",rid);
    map.put("permission",permission);
    return map;
}

前端代码:

function getlogin(){

        $.ajax({
        type: "get",
        url: "http://localhost:8089/user/login",
        data:{
        "loginName":$("#username").val(),
        "password":$("#pwd").val()
        },
        xhrFields:{withCredentials:true},
        beforeSend: function(XMLHttpRequest){
        },
        //请求成功回调
        success: function(data, textStatus){

              if(data.login){
                 alert(data.roleId);
                  localStorage.setItem("token",data.token);
                  localStorage.setItem("roleId",JSON.stringify(data.roleId));
                  localStorage.setItem("uid",data.uid);

                  localStorage.setItem("data",JSON.stringify(data));
                  console.log(localStorage.getItem("data"));
                  window.location.href ="success";

              }
           
        },
        complete: function(XMLHttpRequest, textStatus){
            
        },
        error: function(){
            alert("请求网络失败!。。。。。。");
        }
    });
}
登录成功进入首页
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script typet="text/javascript" src="http://libs.baidu.com/jquery/1.9.1/jquery.min.js"></script>
</head>
<body onload="check()">
<div>
<div>

    <button onclick="changePermission()">用户权限管理</button>
    <li id="select" onclick="selectOne()" style="display: none;">查询用户</li>
    <li id="add" onclick="addOne()" style="display: none;">添加用户</li>
    <li  id="delete" onclick="deleteOne()" style="display: none;">删除用户</li>
    <li id="update" onclick="updateOne()" style="display: none;">修改用户</li>
    <li id="login" onclick="login()" style="display: none;">用户登录</li>
    <li id="submit" onclick="submited()" style="display: none;">用户注册</li>


</div>
    
</div>
<script>


    function selectOne() {
        window.location.href="page/selectOne"
    }

    function addOne() {
        window.location.href="page/addOne"
    }

    function deleteOne() {
        window.location.href="page/deleteOne"
    }

    function updateOne() {
        window.location.href="page/updateOne"
    }

    function login() {
        window.location.href= "login"
    }

    function submited() {
        window.location.href= "page/submit"
    }

    function changePermission() {
        window.location.href="page/change"
    }

    /**
     * 判断数组中是否有某元素
     * @param arr
     * @param obj
     * @returns {boolean}
     */
    function contains(arr, obj) {
        var i = arr.length;
        while (i--) {
            if (arr[i] === obj) {
                return true;
            }
        }
        return false;
    }


    function check(){
        var data = localStorage.getItem("data");
        var arr = JSON.parse(data).permission;
        console.log(arr);

        if(contains(arr, "user.add")){
            document.getElementById("add").style.display="block";
        }
        if(contains(arr,"user.delete")){
            document.getElementById("delete").style.display="block";
        }
        if(contains(arr,"user.update")){
            document.getElementById("update").style.display="block";
        }
        if(contains(arr,"user.select")){
            document.getElementById("select").style.display="block";
        }
        if(contains(arr,"user.login")){
            document.getElementById("login").style.display="block";
        }
        if(contains(arr,"user.submit")){
            document.getElementById("submit").style.display="block";
        }
    }
    

</script>

</body>
</html>

加载该界面就开始通过用户的权限集合对权限做隐藏或显现处理

 function check(){
        var data = localStorage.getItem("data");
        var arr = JSON.parse(data).permission;
        console.log(arr);

        if(contains(arr, "user.add")){
            document.getElementById("add").style.display="block";
        }
        if(contains(arr,"user.delete")){
            document.getElementById("delete").style.display="block";
        }
        if(contains(arr,"user.update")){
            document.getElementById("update").style.display="block";
        }
        if(contains(arr,"user.select")){
            document.getElementById("select").style.display="block";
        }
        if(contains(arr,"user.login")){
            document.getElementById("login").style.display="block";
        }
        if(contains(arr,"user.submit")){
            document.getElementById("submit").style.display="block";
        }
    }
    
③对某用户拥有权限下的所有前端操作进行放行访问,反之拦截

该需求代码在准备工作已陈列,此处省略!

④通过角色id对该用户对应的角色权限进行增删操作

效果图:


点击角色分配,其中的角色是通过后台得到的,前端代码如下

/**
 * 得到角色数组
 */
function getRoleArray() {

        if(contains(roleArray,1)){
           document.getElementById("r1").style.display="block";
            document.getElementById("super").style.display="block";
        }

        if(contains(roleArray,2)){
            document.getElementById("r2").style.display="block";
            document.getElementById("ad").style.display="block";
        }

        if(contains(roleArray,3)){
            document.getElementById("r3").style.display="block";
            document.getElementById("tu").style.display="block";
        }


}
拥有该角色就显示,没有就隐藏,随机点击一项,然后勾选对应角色的权限


点击提交


这样,就为游客赋予了所有的权限了,同样地,删除权限也是相同的道理。

⑥用户角色的赋予

前端选择待添加角色代码:

/**
 * 选择待添加角色
 */
function selectRole() {
    var role = $("#roleSelecte").val();
    var rid;
   alert(roleArray+","+role);

    if("超级管理员" == role){

        rid = 1;
        if(contains(roleArray,1)){
            alert("该用户已拥有此权限")
        }else{
            addRole(rid);
        }
    }else if("管理员" == role){
        rid = 2;
        if(contains(roleArray,2)){
            alert("该用户已拥有此权限")
        }else{
            addRole(rid);
        }
    }else{
        rid = 3;
        if(contains(roleArray,3)){
            alert("该用户已拥有此权限")
        }else{
            addRole(rid);
        }

    }
}
添加角色代码
function addRole(rid) {
    $.ajax({
        type: "get",
        url: "http://localhost:8089/user/addRole",
        data:{
            "uid":uid,
            "rid":rid
        },
        xhrFields:{withCredentials:true},
        beforeSend: function(XMLHttpRequest){
        },
        //请求成功回调
        success: function(data, textStatus){
            if(data.isAdd){
          window.location.href="getRole"
          // alert("添加角色成功!")

            }

        },
        complete: function(XMLHttpRequest, textStatus){

        },
        error: function(){
            alert("请求网络失败!。。。。。。");
        }
    });
}

⑦用户角色的删除

前端选择待删除角色代码:

function SelectDelRole() {
    var role = $("#roleDelete").val();
    var rid;
    alert(roleArray+","+role);

    if("超级管理员" == role){

        rid = 1;
        if(contains(roleArray,1)){
            deleteRole(rid);
        }else{
            alert("该用户无此权限");
        }
    }else if("管理员" == role){
        rid = 2;
        if(contains(roleArray,2)){
            deleteRole(rid);

        }else{
            alert("该用户无此权限");
        }
    }else{
        rid = 3;
        if(contains(roleArray,3)){
            deleteRole(rid);

        }else{
            alert("该用户无此权限");
        }

    }
}
删除角色代码:
function deleteRole(rid) {
    $.ajax({
        type: "get",
        url: "http://localhost:8089/user/deleteRole",
        data:{
            "uid":uid,
            "rid":rid
        },
        xhrFields:{withCredentials:true},
        beforeSend: function(XMLHttpRequest){
        },
        //请求成功回调
        success: function(data, textStatus){
            if(data.isDelete){
                window.location.href="getRole"
               // alert("角色删除成功!")

            }

        },
        complete: function(XMLHttpRequest, textStatus){

        },
        error: function(){
            alert("请求网络失败!。。。。。。");
        }
    });
}
无论添加或者删除角色,都对角色进行刷新操作
var uid = localStorage.getItem("uid");
function flushRole() {
    $.ajax({
        type: "get",
        url: "http://localhost:8089/user/getRoleId",
        data:{
            "uid":uid
        },
        xhrFields:{withCredentials:true},
        beforeSend: function(XMLHttpRequest){
        },
        //请求成功回调
        success: function(data, textStatus){
            if(data.status){
                localStorage.setItem("roleId",JSON.stringify(data.roleId));
               window.location.href = "change";

            }

        },
        complete: function(XMLHttpRequest, textStatus){

        },
        error: function(){
            alert("请求网络失败!。。。。。。");
        }
    });
}

猜你喜欢

转载自blog.csdn.net/architect_csdn/article/details/80238939