登陆权限设置 根据权限设置菜单

1.在项目添加权限

shiro处理权限流程:

​ (1)把所有的权限交给shiro管理 --createFilterChainDefinitionMap 可以体现处理

​ (2)在realm里面 就要查询当前用户的权限,如果这个权限在shiro管理返回之内,这个用户就有响应的权限

否则就没有

1.1 从数据库查询所有权限交个shiro管理

 // 从数据库啊查询到所有的权限 交给shiro管理
        List<Permission> all = iPermissionService.findAll();
        for (Permission Permission : all) {
            // 权限对应的资源请求地址
            String url = Permission.getUrl();
            //权限
            String sn = Permission.getSn();
        // 放进map交给shiro管理  aisellPerms去找我们自己写的自定义的过滤器  Perms默认值找的是shiro的过滤器我们继承复写后需要改成我们自己的
            mp.put(url, "aisellPerms[" + sn + "]");
        }

如何体现将 map里面的权限交给shiro管理呢:
配置自定义权限过滤器

        自定义权限过滤必须有  使用自定义的权限过滤器必须有工厂bena的支持才能使用 
            

 <!-- 真实的过滤器处理 id这个名字 必须和web.xml里面配置的代理的过滤器的名称一样,才行-->
    <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
        <property name="securityManager" ref="securityManager"></property>

        <!-- 如果没有认证,会跳转该页面-->
        <property name="loginUrl" value="/login"></property>
        <!--认证成功,跳转的页面-->
        <property name="successUrl" value="/main"></property>
        <!--没有权限-->
        <property name="unauthorizedUrl" value="/s/unauthorized.jsp"></property>

        <!--配置自定义过滤器-->
<property name="filters">
    <map>
        <entry key="aisellPerms" value-ref="aisellPermsFilter">
        </entry>
    </map>
</property>
        <!--拦截配置-->
        <property name="filterChainDefinitionMap" ref="filterChainDefinitionMap1"></property>
    </bean>


    <!-- 定义自定义过滤器-->
    <bean id="aisellPermsFilter"
          class="cn.itsource.aisell.shiro.AisellFilterChainDefinitionMapBuilder"></bean>
    <!-- 配置两个bean   引用map这个类 就动态的拿到了每个用户的权限-->
    <bean id="filterChainDefinitionMap1" factory-bean="filterMapFactoyBean" factory-method="createFilterChainDefinitionMap">
    </bean>
   <!--   引用map这个类 就动态的拿到了每个用户的权限就能进行拦截和放行-->
    <bean id="filterMapFactoyBean" class="cn.itsource.aisell.shiro.AisellFilterChainDefinitionMap"></bean>
 



1.2 查询当前用户具备权限

--sql语句查询当前用户的权限
select p.* from employee e
join employee_role er on e.id = er.employee_id
join role r on er.role_id = r.id
join role_permission rp on rp.role_id = r.id
join permission p on p.id = rp.permission_id 
where e.id = 2

  jpql查询语句
  @Query("select p.sn from Employee e join e.roles er join er.permissions p where e.id = ?1 ")
    public Set<String> findPermissionsByLoginUser(Long id);

  当你前台登录后就会将登陆对象传到后台来验证  验证结束后进入如此方法授权
 protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        //授权方法
        Employee employee =(Employee) principalCollection.getPrimaryPrincipal();
      /*根据用户名得到权限代码
        从数据库查询当前用户的所有的权限
       三层架构通过用户id去查询 用户权限 连表查寻*/
       // Set<String> permissions = getPermissionsByUsername(employee.getUsername());
        Set<String> permissionSet = permissionService.findPermissionByEmployeeId(employee.getId());
        //shiro就会自己取进行权限的比较
        SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
        authorizationInfo.setStringPermissions(permissionSet);
        return authorizationInfo;
    }

1.3 权限出问题之后,ajax怎么返回

为什么会出现这个问题 shiro底层不会处理你ajax请求 所以你发送ajax请求若是权限不够则 会弹出框 Undefined (该提示并不能满足我们的需求)
解决方式:

(1)写一个过滤器 覆写PermissionsAuthorizationFilter

(2)重写 onAccessDenied方法

​ 方法里面 就判断如果是ajax请求 就直接返回json格式,

​ 否则就走原来的格式,返回页面

     public class AisellFilterChainDefinitionMapBuilder extends PermissionsAuthorizationFilter {
    //没有权限的时候 返回的方法
    /**
     *  判断请求是否是ajax请求。如果是ajax请求,直接返回json格式
     *  否则走它以前的返回页面的代码
     *   就是一个自定义的拦截器的类
   */
    @Override
    protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws IOException {
        // 通过请求拿到主体对象
        Subject subject = this.getSubject(request, response);
       // System.out.println(subject.getPrincipal());
        //  得到的用户若是为空则表示没有登录
        if (subject.getPrincipal()==null){
           //没有登录成功后的操作
            this.saveRequestAndRedirectToLogin(request, response);
        }else {
           // 强转为子类方法多啊
            HttpServletRequest req=  (HttpServletRequest)request;
            HttpServletResponse resp=(HttpServletResponse) response;
            // 判断是否使ajax请求该方法会得到一个返回值     若是ajax请求的话再请求头里面会有这个key属性呢 X-Requested-With
            String header = req.getHeader("X-Requested-With");

             // 判断返回的是否是ajax的请求 XMLHttpRequest 是ajax请求的value
             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;
    }

}

将自定义的过滤器配置到 applicationcontext-shiro.xml 里面

        <!--配置自定义过滤器-->
<property name="filters">
    <map>
        <entry key="aisellPerms" value-ref="aisellPermsFilter">
        </entry>
    </map>
<!-- 定义自定义过滤器-->
    <bean id="aisellPermsFilter"
          class="cn.itsource.aisell.shiro.AisellFilterChainDefinitionMapBuilder"></bean>

配置完毕后 还需要再发送请求的时候找到自定义过滤器: 参见map里面的配置

1.4 页面权限的按钮控制

添加标签来控制页面的按钮是否显示 shiro会通过这个标签自己判断是否有权限

  //  引入标签库支持
 <%@ taglib prefix="shiro" uri="http://shiro.apache.org/tags" %>


 <shiro:hasPermission name="employee:delete">
             <a href="#" data-method="delete" plain="true"   class="easyui-linkbutton" iconCls="icon-remove">删除</a>
  </shiro:hasPermission>

2 左侧树形菜单

需求:动态获取菜单根据用户权限显示菜单

2.1 menu对象的确定

写了Menu domain对象

public class Menu extends BaseDomain {

    private String name;//菜单名称
    private String url; //路径
    private String icon; //图标
    //配置懒加载
    @ManyToOne(fetch = FetchType.LAZY)
    // 表名
    @JoinColumn(name="parent_id")
    @JsonIgnore //忽略json 在展示json格式的 parent不会展示出来 会造成死循环
    private Menu parent;

    @Transient //这个是临时属性,不交给jpa管理 ,自己来维护 -- 手动添加子菜单
    private List<Menu> children = new ArrayList();

    //兼容esayui的菜单树[id:1,text:'xxx'] esayui的格式是text
    public String getText(){
        return this.name;
    }
    //setget...
    }

2.2 service构造json的方法

public List<Menu> findMenuByLoginUser(Long employeeId) {
        List<Menu> menus = new ArrayList();
        //查询当前用户的所有的子菜单
        List<Menu> subMenus = menuRepository.findByLoginUser(employeeId);
        //循环子菜单  2,3,4,5    1   (7 8)  6
        for (Menu subMenu : subMenus) {
            //从子菜单里面拿到父菜单 6
            Menu parentMenu = subMenu.getParent();
            // 判断集合里面是否有这个对象
            if(!menus.contains(parentMenu)) {
            //若是没有则添加一个
                menus.add(parentMenu);
            }
            //通过父菜单查询出子菜单 放到对象里面去
            parentMenu.getChildren().add(subMenu);//[1,[2,3,4,5],6 [7,8]]
        }

        return menus;
    }
发布了23 篇原创文章 · 获赞 2 · 访问量 934

猜你喜欢

转载自blog.csdn.net/metjoyful/article/details/102508615