zoukankan      html  css  js  c++  java
  • shiro权限框架

    权限的组成部分:用户 资源 角色 权限

    数据库关系表设计是根据自己项目需求设计的

    account表
    role表(id,rolename)
    account_role(id,aid,rid)
    permission(id,pername)
    role_permission(id,rid,pid)

     没有设置用户和权限的关系,我们可以认为用户的权限是通过角色来决定的

    1.导入jar包

    shiro-all-1.2.1.jar

    2.配置web.xml

        <!-- 权限过滤器-->
      <filter>
          <filter-name>shiroFilter</filter-name>
        <!-- 委托给spring,所以还要在spring中配置 -->
          <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
      </filter>
      <filter-mapping>
          <filter-name>shiroFilter</filter-name>
          <url-pattern>/*</url-pattern>
      </filter-mapping>

    3.新建applicationContext-shiro.xml 

    因为在web.xml中有配置spring容器,它会读取applicationContext开头的配置文件
    <context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>classpath:applicationContext*.xml</param-value>
    </context-param>

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="
    http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"
    >
        <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
            <property name="cacheManager" ref="cacheManager"/>
            <!-- 权限框架的操作类 myShiroRealm,可以service中新建这个类-->
            <property name="realm" ref="myShiroRealm"/>
        </bean>
        
        <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
            <property name="securityManager" ref="securityManager"/>
            
            <!-- 以下是跟登录权限有关的配置 -->
            
            <!-- 配置登录的url -->
            <property name="loginUrl" value="/"/>
            <!-- 登录成功的url -->
            <property name="successUrl" value="/book/1"/>
            <!-- 没有权限的url -->
            <property name="unauthorizedUrl" value="/403"/>
            
            <property name="filterChainDefinitions">
                <value>
                
                    <!-- 静态资源不用认证 要放在/** = authc之前,因为当所有的都要认证的时候再写它就没用了-->
                    /static/** = anon
                    <!-- 角色配置,没有管理员这个角色的账户是不能访问/book/**里面的内容的 -->
                    /book/** = roles[管理员]
                    <!-- 权限配置,不要只在界面上用标签配置 没有book:add的权限的账户是不能访问/book/add的
                        但是如果没有权限你还是要访问的话,就要到上面的<property name="unauthorizedUrl" value="/403"/>
                        里面了,自定义一个403页面,这里举出一个例子,可以在mvc-servlet配置静态资源
                        <mvc:view-controller path="/403" view-name="403"/>-->
                    /book/add = perms[book:add]
                    
                    <!-- (根目录及其子目录)所有的资源都是需要认证的 这个时候以前mvc-servlet里面的拦截器就不用写了-->
                    /** = authc
                </value>
            </property>
        </bean>
        
        <bean id="cacheManager"
            class="org.apache.shiro.cache.MemoryConstrainedCacheManager" />
        <bean id="lifecycleBeanPostProcessor"
            class="org.apache.shiro.spring.LifecycleBeanPostProcessor" />
    
    
    </beans>

    举例

    package com.kaishengit.service;
    
    import javax.inject.Inject;
    import javax.inject.Named;
    
    import org.apache.shiro.authc.AuthenticationException;
    import org.apache.shiro.authc.AuthenticationInfo;
    import org.apache.shiro.authc.AuthenticationToken;
    import org.apache.shiro.authc.SimpleAuthenticationInfo;
    import org.apache.shiro.authc.UsernamePasswordToken;
    import org.apache.shiro.authz.AuthorizationInfo;
    import org.apache.shiro.authz.SimpleAuthorizationInfo;
    import org.apache.shiro.realm.AuthorizingRealm;
    import org.apache.shiro.subject.PrincipalCollection;
    
    import com.kaishengit.pojo.Admin;
    
    // 需要继承自AuthorizingRealm并实现它的方法
    @Named
    public class MyShiroRealm extends AuthorizingRealm{
    
        @Inject
        private AdminService adminService;
        
        
        /**
         * 权限认证方法
         */
        @Override
        protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection pCollection) {
            //获取当前登录的用户名
            String loginName = (String) pCollection.fromRealm(getName()).iterator().next();
            
            Admin admin = adminService.findByName(loginName);
            if(admin != null) {
                SimpleAuthorizationInfo sInfo = new SimpleAuthorizationInfo();
                //1. 获取当前用户拥有的所有角色
                sInfo.setRoles(adminService.getRoles(admin));
                /* adminService中的该方法
                    public Set<String> getRoles(Admin admin) {
                        List<Role> roles = roleDao.findByAdminId(admin.getId());
                        因为是要返回的set集合
                        Set<String> roleNames = new HashSet<String>();
                        
                        for(Role r : roles) {
                            roleNames.add(r.getRolename());
                        }
                        return roleNames;
                    }*/
                
                //2. 获取当前用户拥有的所有权限
                // 还有一个方法,跟下面的不同的是set第二次会覆盖,add表示添加
                //sInfo.addStringPermissions(adminService.getPermissions(admin));
                sInfo.setStringPermissions(adminService.getPermissions(admin));
                
                /* adminService中的该方法
                    public Set<String> getPermissions(Admin admin) {
                        一个账户可能有多个角色
                        List<Role> roles = roleDao.findByAdminId(admin.getId());
                        
                        Set<String> permissions = new HashSet<String>();
                        
                        for(Role role : roles) {
                            一个角色可能有多个权限
                            List<Permission> perList = permissionDao.findByRoleId(role.getId());
                            for(Permission p : perList) {
                                装入set集合
                                permissions.add(p.getPername());
                            }
                        }
                        return permissions;
                    }
                    */
                return sInfo;
            }
            
            
            return null;
        }
    
        /**
         * 登录认证方法
         */
        @Override
        protected AuthenticationInfo doGetAuthenticationInfo(
                AuthenticationToken auToken) throws AuthenticationException {
            // 强制转换
            UsernamePasswordToken token = (UsernamePasswordToken) auToken;
            // 通过名字查询,用的是token.getUsername,那这个名字是从哪里放进来的呢,是在controller中new出来
            //    的token,然后传进去的账户信息,然后在这里get
            Admin admin = adminService.findByName(token.getUsername());
            
            if(admin != null) {
                // 如果查询得到一个admin就算登录成功 ,因为下面的构造函数会传入账户和密码,然后自动检测 
                return new SimpleAuthenticationInfo(admin.getName(),admin.getPassword(),getName());
            }
            return null;
        }
    
    }
    @Controller
    public class AdminController {
    
        @Inject
        private AdminService adminService;
        
        @RequestMapping(value="/",method=RequestMethod.POST)
        public String login(Admin admin,HttpSession session,RedirectAttributes redirectAttributes) {
            
            try {
                /* 在这里new出来 UsernamePasswordToken,传入账户信息
                    当在这里调用login的时候就会自动调用MyShiroRealm中登录认证的那个方法
                    
                    这个方法是不会抛出异常的,但是我们还是要try catch一下,因为这个方法不能做判断
                        所以当来到catch的时候就说明登录失败了*/
                SecurityUtils.getSubject().login(new UsernamePasswordToken(admin.getName(), admin.getPassword()));
                return "redirect:/book/1";
            } catch (AuthenticationException e) {
                redirectAttributes.addFlashAttribute("message", "账号或密码错误");
                return "redirect:/";
            }
            
            
            
            /*
            这是以前的方法
            Admin currAdmin = adminService.login(admin.getName(),admin.getPassword());
            if(currAdmin == null) {
                redirectAttributes.addFlashAttribute("message", "账号或密码错误");
                return "redirect:/";
            } else {
                session.setAttribute("curr_admin", currAdmin);
                return "redirect:/book";
            }*/
        }
        
        
        
    }

     jsp中对应的标签 
     首先导入标签 

    <%@ taglib prefix="shiro" uri="http://shiro.apache.org/tags" %>

    <!-- 该账户有的角色中存在权限 book:add权限的话就能添加书籍-->
    <shiro:hasPermission name="book:add">
        <a href="/book/add" class="btn btn-success">添加书籍</a>
    </shiro:hasPermission>
    
    <table class="table">
        <thead>
            <tr>
                <th>书籍编号</th>
                <th>书籍名称</th>
                <th>作者</th>
                <th>出版社</th>
                <th>总数量</th>
                <th>当前数量</th>
                <th>#</th>
            </tr>
        </thead>
        <tbody>
            
            <c:forEach items="${bookList }" var="book">
                <tr>
                    <td>${book.code }</td>
                    <td>${book.name }</td>
                    <td>${book.author }</td>
                    <td>${book.publish }</td>
                    <td>${book.total}</td>
                    <td>${book.nowcount }</td>
                    <td>
                        <shiro:hasPermission name="book:edit">
                            <a href="/book/edit/${book.id }">修改</a>
                        </shiro:hasPermission>
                        <shiro:hasPermission name="book:remove">
                            <a href="/book/del/${book.id }">删除</a>
                        </shiro:hasPermission>
                    </td>
                </tr>
            </c:forEach>
        </tbody>
    </table>

    这个标签只是在界面上控制不让它显示,但是如果在url上直接进入还是控制不住的,所以要在
    applicationContext-shiro.xml 配置,见上...

  • 相关阅读:
    sql server 中having 的使用注意事项
    js截取字符串
    .net截取字符串
    序列化二叉树
    把二叉树打印成多行
    35 拷贝赋值函数、虚函数
    34 char类型转换为int类型
    33 单/双精度有效数字、程序运行过程
    32 C++常见错误集锦
    31 位域、空类的sizeof值
  • 原文地址:https://www.cnblogs.com/itliucheng/p/4298989.html
Copyright © 2011-2022 走看看