智能商贸系统之存销宝Day07权限

权限过滤

FilterChainDefinitionMapFactory

//查询出所有的权限
 List list = permissionService.findAll();
 //遍历list集合,并将表permission中所有的权限遍历出来
        list.forEach(e->{
            map.put(e.getUrl(),"mpf["+e.getSn()+"]");
        });

修改主体

将之前传入的是username,现在通过当前用户查询处employee对象,再将此对象loginUser传入

  SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(loginUser, loginUser.getPassword(),salt, getName());

修改主页面main.jsp

由于上面把login传入了,导致当前登录页面显示的是一个对象,所以需要修改,这样就可以显示当前用户了

 
亲爱的欢迎你,注销

提供一个获取当前用户的公共类

package com.yanzhengwei.common;
import com.yanzhengwei.domain.Employee;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.subject.Subject;
public class UserContext {
    //设置一个key值
    public static final String USER_IN_SESSION ="loginUser";
    public static void setUserInSession() {
        //设置当前用户
        Subject subject = SecurityUtils.getSubject();
        //拿到当前用户主体
        Employee user = (Employee)subject.getPrincipal();
        subject.getSession().setAttribute(USER_IN_SESSION,user);
    }
    public static Employee getUserInSession() {
        //设置当前用户
        Subject subject = SecurityUtils.getSubject();
        Employee user = (Employee) subject.getSession().getAttribute(USER_IN_SESSION);
        return user;
    }
}

LoginController

修改控制登录的controller,在登录成功之后,将当前用户存入session中.

根据当前用户id拿权限(权限对应的各层)

Repository

    @Query("select distinct p.sn from Employee e join e.roles r join r.permission p where e.id=?1")
    Set findAllToPermission(Long id);

service

Set findAllToPermission(Long id);

serviceImpl

    public Set findAllToPermission(Long id) {
        return permissionRepository.findAllToPermission(id);

修改权限验证判断

在前一张中的权限是用的模拟数据库中获取,本章权限数据将从数据库中获取

 //拿到需要验证的用户,强转,不然会出现类型转换异常,之前是强转为String
        Employee employee = (Employee)principals.getPrimaryPrincipal();
        //查询数据库得到当前用户的权限
        Set allToPermission = permissionService.findAllToPermission(employee.getId());
        //创建授权对象
        SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
        //设置角色和权限
        simpleAuthorizationInfo.setStringPermissions(allToPermission);

上面的代码完成以后就可以查看每个用户相应的权限了,接下来我们来解决bug

删除/修改/添加权限

如果一个用户没有这些权限,应该是看不到相关的按钮操作,但是我们先不做这个,如果没有权限,而去修改的话需要修改之前的代码,由于之前的这些功能我们用的是ajax请求来做的,如果没有权限做这些操作,提示弹框还有undefined,所以我们要更改该显示,其实造成这个的原因是后台返回的是一个错误页面

自定义一个拦截器

package com.yanzhengwei.common;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.util.StringUtils;
import org.apache.shiro.web.filter.authz.PermissionsAuthorizationFilter;
import org.apache.shiro.web.util.WebUtils;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
//自定义权限过滤器,并交给Spring管理
public class MyPermissionsAuthorizationFilter extends PermissionsAuthorizationFilter {
    @Override
    protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws IOException {
        //得到当前用户
        Subject subject = this.getSubject(request, response);
        //判断当前有无用户主体
        if (subject.getPrincipal() == null) {
            //有主体但是没有登录成功跳转到默认的登陆页面
            this.saveRequestAndRedirectToLogin(request, response);
        } else {
            //获得httpServletRequest和HttpServletResponse
            HttpServletRequest req = (HttpServletRequest) request;
            HttpServletResponse resp = (HttpServletResponse) response;
            //获得请求的头
            String header = req.getHeader("X-Requested-With");
            //根据请求头判断是ajax请求还是普通请求
            if (header != null && "XMLHttpRequest".equals(header)) {
                //如果程序执行到此就是ajax请求
                //响应的类型设置为json
                resp.setContentType("text/json;charset=UTF-8:");
                //响应具体内容
                resp.getWriter().print("{\"success\":false,\"msg\":\"抱歉,你没有权限,请联系超管\"}");
            } else {
                String unauthorizedUrl = this.getUnauthorizedUrl();
                if (StringUtils.hasText(unauthorizedUrl)) {
                    WebUtils.issueRedirect(request, response, unauthorizedUrl);
                } else {
                    WebUtils.toHttp(response).sendError(401);
                }
            }
        }
        return false;
    }
}

代码完成之后,需要告诉有Spring管理的shiro,要执行这个过滤

 
    

        
            
            //这个key中的mpf就是为这个过滤器取得一个别名,文章开头中的FilterChainDefinitionMapFactory类中用的便是这个mpf
                
            
        

菜单Menu读取

首先使用代码生成器生成Menu所有对的层级结构

修改Menu

 @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name="parent_id")
    @JsonIgnore //这里生成json的时候要忽略,否则会造成功能相互调用
    private Menu parent;
    /**
     * 还要配置一个一对多
     *  这个字段不要交给JPA管理【到时候自己写代码管理】
     *  数据库的menu表中就应该有一个children,而且还是List类型
     *  Transient:临时属性(JPA不管这个属性,和数据库没有关系)
     */
    @Transient
    private List children = new ArrayList<>();
    …
   public String getText(){ //EasyUI的树需要一个text属性
      return name;
    }

修改Permission

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name="menu_id")
private Menu menu;

完成查询层结构

将Employee/Role/Permission/Menu四表联系起来,通过employeeId查询出权限菜单的查询

MenuRepository

@Query("select distinct m from Employee e join e.roles r join r.permissions p join p.menu m where e.id = ?1")
List findByLoginUser(Long userId);

MenuService

@Override
public List findByLoginUser(Long userId) {
    //准备父菜单容器
    List parentMenus = new ArrayList<>();
    //从数据库中拿到子菜单
    List childrenMenus = menuRepository.findByLoginUser(userId);
    //遍历子菜单(如果有父菜单放进入,没有单独创建)
    for (Menu childrenMenu : childrenMenus) {
        //拿到子菜单对应的父菜单
        Menu parent = childrenMenu.getParent();
        //判断如果父菜单中是否有这个菜单
        if(parentMenus.contains(parent)){
            //有的话,咱们就把子菜单放到父菜单中去
            int i = parentMenus.indexOf(parent);
            Menu parentMenu = parentMenus.get(i);
            parentMenu.getChildren().add(childrenMenu);
        }else{
            //如果没有,再单独把父菜单放进去
            parentMenus.add(parent);
            parent.getChildren().add(childrenMenu);
        }
    }
    return parentMenus;
}

UtilController

//获取当前用户的菜单列表
    @RequestMapping("/menuByUser")
    @ResponseBody
    public List menuByUser(){
        //通过工具获得当前用户
        Employee user = UserContext.getUserInSession();
        return menuService.findMenuByUser(user.getId());
    }

修改main.jsp

修改tree的路径

 $(function () {
        var regionTree = $('#regionTree');
        regionTree.tree({
            url:'/util/menuByUser'
        });

关于修改/添加/删除权限的补充

在前面我们说了,没有这些权限的用户,是应该不显示这个操作按钮的,所以我们接下来完成这个配置
首先找到对应员工的jsp页面配置如下:

1://引入shiro
<%@taglib prefix="shiro" uri="http://shiro.apache.org/tags" %>
2://在这些功能的便签上加上
 
            添加
        
        
            修改
        
        
            删除
        

你可能感兴趣的:(java)