wisdomsell-day7(智能商贸系统第七天)

wisdomsell-day7(智能商贸系统第七天)

1.权限判断

权限的拦截也应该是从数据库中获取

public class FilterChainDefinitionMapFactory{
    @Autowired
    private IPermissionService permissionService;
     //添加权限拦截数据(应该从数据库中获取)
        List<Permission> perms = permissionService.findAll();
        perms.forEach(p->{
            //perms:PermissionsAuthorizationFilter
            //aisellPerms:AiSellPermissionsAuthorizationFilter
            map.put(p.getUrl(),"perms["+p.getSn()+"]");
        });
}

1.1从数据库中获取用户的权限

public interface PermissionRepository extends BaseRepository<Permission,Long> {
    /**
     * 根据用户获取到它的权限
     * 返回的是Set<String>
     *     JPQL关连法则: 1.关连前面的类的别名.属性 2.不需要你消除笛卡尔积
     */
    @Query("select p.sn from Employee e join e.roles r join r.permissions p where e.id=?1")
    Set<String> findSnByUser(Long userId);

}

1.2拿到当前用户的对象

public class UserContext {
    /**
     *
     * 拿到当前登陆用户
     * 封装成一个类,后面有重复得直接调用就行
     这里通过主体来获取,只要得到主体,就可以在任意地方获取对象
     */
    public static Employee getUser(){
        Subject subject = SecurityUtils.getSubject();
        Employee loginUser = (Employee)subject.getPrincipal();
        return loginUser;
    }
}

1.3完成service层里面代码

public interface IPermissionService extends IBaseService<Permission,Long> {
    //根据当前用户获取对应权限
    Set<String> findSnByUser();
}
public class PermissionServiceImpl extends BaseServiceImpl<Permission,Long> implements IPermissionService {

    @Autowired
    private PermissionRepository permissionRepository;
    @Override
    public Set<String> findSnByUser() {
        Employee loginUser = UserContext.getUser();
        return permissionRepository.findSnByUser(loginUser.getId());
    }
}

2.权限的ajax问题

我们在发送请求时有两种请求,一种是ajax请求,另外一种是普通请求,对于普通请求,没有权限的处理的方式就是跳转到一个页面,然后显示消息,而ajax请求对于没有权限的处理直接就在当前页面显示就可以

2.1用自定义拦截器

通过自定义拦截器就可以即保留普通请求,通过也能保留ajax请求

/**
 * 自定义一个拦截器,现在发送请求一个是ajax请求,另外一个是普通的请求
 * 普通请求是跳转到页面,这就导致在员工页面进行删除操作时,如果没有该权限,就会出错,现在我们自己配置一个拦截器,如果没有该权限
 * 根据发送的请求不同,进入不同的操作,ajax请求和普通请求最主要的区别有无X-Requested-With
 * 这里本来应该继承PermissionsAuthorizationFilter的父类AuthorizationFilter
 * 但是为了保留PermissionsAuthorizationFilter里面的功能,所以继承PermissionsAuthorizationFilter
 * 但是实现的方法还是用的父类的方法
 */
public class MyPermissionsAuthorizationFilter extends PermissionsAuthorizationFilter {
    protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws IOException {
        Subject subject = this.getSubject(request, response);
        if (subject.getPrincipal() == null) {
            this.saveRequestAndRedirectToLogin(request, response);
        } else {
            //1.转换成http对象
            HttpServletRequest req = (HttpServletRequest)request;
            HttpServletResponse resp = (HttpServletResponse)response;
            //2.获取到头,根据头来进行判断
            String header = req.getHeader("X-Requested-With");
            //3.处理成为ajax数据
            if("XMLHttpRequest".equals(header)){
                resp.setContentType("application/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 {
                    //如果没有路径,就会出401错误
                    WebUtils.toHttp(response).sendError(401);
                }
            }

        }

        return false;
    }

}

2.2将自定义拦截器引入到shiro中

 <property name="filters">
            <map>
                <entry key="myperms" value-ref="myPermissionsAuthorizationFilter"></entry>
            </map>
        </property>
        
         <bean id="myPermissionsAuthorizationFilter" class="com.yyk.aisell.web.shiro.MyPermissionsAuthorizationFilter"></bean>
//将权限拦截的名字改为自定义拦截的名字
map.put(p.getUrl(),"perms["+p.getSn()+"]");
//改为
map.put(p.getUrl(),"myperms["+p.getSn()+"]");

3.配置菜单的crud

和前面的权限以及角色一样,复制然后替换为相对应的字段

4.配置一对多

这里我们选择通过父菜单去找子菜单,配置为一对多关系,这样右边可以显示数据库中的菜单,但是是没有层级的,如果想配置为有层级关系的,配置一对多在这里就会出现问题。因为jsp在处理通过一对多去找子菜单时,会将它的所有子类菜单都找出来,这样是不符合要求的,所以这里不能配置一对多关系,而应该配置为多对一,但是应该保留一对多的字段

/**
     * 这里如果一开始配置一对多关系,即通过父类去找到子类菜单,是没有问题的,但是前台展示就没有层级关系,如果你要有层级关系
     * jpa在通过父类去寻找子类时,是把所有的子类找出来,这样是不行的,但是这个字段是一定要保留的
     * 那么只能通过子类去寻找父类,配置一对多的关系
     * @Transient临时的,让jpa不要去管他,以后如果有必须要存在的字段,但是数据库中没有该字段,就通过这个注解解决
     */
    @Transient
    private List<Menu> children = new ArrayList<>();

    @ManyToOne
    @JoinColumn(name="parent_id"
    private Menu parent;

4.1完成service层代码

接口

List<Menu> findParentMenus();

实现类

public class MenuServiceImpl extends BaseServiceImpl<Menu,Long> implements IMenuService {

    @Autowired
    private MenuRepository menuRepository;
    @Override
    public List<Menu> findParentMenus() {
        //1.准备一个空的父菜单容器
        List<Menu> parentMenus = new ArrayList<>();
        //2.拿到用户
        Employee loginUser = UserContext.getUser();
        //3.拿到这个用户的菜单
        List<Menu> menus = menuRepository.findMenusByUser(loginUser.getId());
        //4.遍历这个子菜单
        menus.forEach(m->{
            //通过子菜单去获得父菜单
            Menu parentMenu = m.getParent();
            //进行判断,如果容器里面没有该父菜单,进放入该父菜单,如果有,就不要管他
            if(!parentMenus.contains(parentMenu)){
                parentMenus.add(parentMenu);
            }
            //将子菜单也要放入到该容器中,因为现在该容器只有父菜单
            parentMenu.getChildren().add(m);
        });
        return menuRepository.findParentMenus();
    }

}

4.2完成dao层里面代码

public interface MenuRepository extends BaseRepository<Menu,Long> {
    //连接数据库中的菜单
    @Query("select o from Menu o where o.url is null ")
    List<Menu> findParentMenus();
    //
    @Query("select distinct m from Employee e join e.roles r join r.permissions p join p.menu m where e.id=?1")
    List<Menu> findMenusByUser(Long userId);
}

4.3完成permission权限里面的多对一关联

  //配置与菜单的外键关系
    @ManyToOne
    @JoinColumn(name="menu_id")
    private Menu menu;

5.解决json数据量过大问题(死循环)

在menu类中加入注解 @JsonIgnore

/**
JsonIgnore:SpringMVC传json就不会使用这个字段了
*/
@ManyToOne
    @JoinColumn(name="parent_id")
    @JsonIgnore
    private Menu parent;

6.通过引入标签的形式来将用户没有的权限隐藏

在role角色jsp页面中

<%--引入通过标签去隐藏没有的权限,即登陆的时候不显示没有的权限--%>
<%@ taglib prefix="shiro" uri="http://shiro.apache.org/tags" %>

<shiro:hasPermission name="employee:delete">
        <a href="#" data-method="delete" class="easyui-linkbutton" iconCls="icon-remove" plain="true">删除</a>
        </shiro:hasPermission>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值