简单的权限(拦截)管理

2020-03-11 14:19:22 浏览数 (1)


简单的权限(拦截)管理

  • 给特定的用户以不同的权限来访问不同的资源
  • 很多人把权限模型理解为 用户—权限,这样不是不可以,是不够好。因为如果有100个用户,20个权限呢?给每个用户单独一个个设置不太现实,所以这时候就要加入另一个模块(角色),结构模型如下:

1. 建5张表

用户

代码语言:javascript复制
CREATE TABLE `user` (
  `id` int(11) NOT NULL,
  `username` varchar(255) NOT NULL,
  `password` varchar(255) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

角色

代码语言:javascript复制
CREATE TABLE `role` (
  `id` int(11) NOT NULL,
  `name` varchar(255) DEFAULT NULL,
  `description` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

权限

代码语言:javascript复制
CREATE TABLE `privilege` (
  `id` int(11) NOT NULL,
  `name` varchar(255) DEFAULT NULL,
  `description` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

用户角色关系表

代码语言:javascript复制
CREATE TABLE `user_role` (
  `user_id` int(11) NOT NULL,
  `role_id` int(11) NOT NULL,
  PRIMARY KEY (`user_id`,`role_id`),
  CONSTRAINT `role_id_fk` FOREIGN KEY (`role_id`) REFERENCES `role` (`id`),
  CONSTRAINT `user_id_fk` FOREIGN KEY (`user_id`) REFERENCES `user` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

角色权限关系表(外键不能重名)

代码语言:javascript复制
CREATE TABLE `role_privilege` (
  `role_id` int(11) NOT NULL,
  `privilege_id` int(11) NOT NULL,
  PRIMARY KEY (`role_id`,`privilege_id`),
  CONSTRAINT `privilege_id_fk` FOREIGN KEY (`privilege_id`) REFERENCES `privilege` (`id`),
  CONSTRAINT `role_id_fk1` FOREIGN KEY (`role_id`) REFERENCES `role` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

查询用户的所有角色

代码语言:javascript复制
SELECT * FROM role WHERE id IN (SELECT role_id FROM user_role WHERE user_id=1);

查询角色的所有权限

代码语言:javascript复制
SELECT * FROM privilege WHERE id IN (SELECT privilege_id FROM role_privilege WHERE role_id=1);

查询用户的所有权限

代码语言:javascript复制
SELECT * FROM privilege WHERE id IN (SELECT DISTINCT privilege_id FROM role_privilege WHERE role_id IN (SELECT role_id FROM user_role WHERE user_id=1));

2. Bean对象

Privilege

代码语言:javascript复制
public class Privilege {
    
    int id;
    String name;
    String description;
    
    public Privilege(String name) {
        this.name = name;
    }
    
    //getters和setters
}

3. Dao层(这里只写获取全部权限)

代码语言:javascript复制
public class PrivilegeDao {
    public HashSet<Privilege> getAllPrivilege(String user_id) {
       
        //各种逻辑操作
        
        return Privileges;
    }
}

4. 拦截功能

  • 使用contains()方法需要在权限类上重写hashCode()和equals()方法的。因为我们比较的是字符串。
代码语言:javascript复制
public class PermissionInterception implements Filter {
    
    //存放需要权限的资源地址
    private Map<String, Object> map = new HashMap<>();

    public void init(FilterConfig filterConfig) throws ServletException {
        map.put("/addServlet", new Privilege("增加"));
        map.put("/deleteServlet", new Privilege("删除"));
        map.put("/updateServlet", new Privilege("修改"));
        map.put("/findServlet", new Privilege("查账单"));
    }
    
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        
        HttpServletRequest httpServletRequest = (HttpServletRequest) request;
        HttpServletResponse httpServletResponse = (HttpServletResponse) response;
         
        //获取请求地址
        String uri = httpServletRequest.getRequestURI();
        
        //公开地址,直接放行
        if (map.get(uri) == null) {
            chain.doFilter(request, response);
            return ;
        }
        
        //需要权限的地址,即要先登录
        if (httpServletRequest.getSession().getAttribute("user") == null) {
            httpServletResponse.sendRedirect("/login.html");
            return;
         }
        
        //查询用户的所有权限,返回一个权限集合
        PrivilegeService privilegeService = new PrivilegeService();
        int user_id = (int) httpServletRequest.getSession().getAttribute("user_id");
        HashSet privileges = privilegeService.getAllPrivilege(user_id);
        
        //是否拥有访问该地址的权限
        if (!privileges.contains(map.get(uri))) {
            httpServletResponse.sendRedirect("/404.html");
            return ;
         }
        
        //通过权限认证,放行
        chain.doFilter(httpServletRequest, httpServletResponse);
        
    }

    public void destroy() {
    }
}

参考Java3y

0 人点赞