zoukankan      html  css  js  c++  java
  • Shiro入门3

    接上一篇内容,对之前的配置文件做一些修改。

     在web.xml中加入编码格式过滤器,从而就可以正常接收中文字符。

     1     <filter>
     2         <filter-name>characterEncodingFilter</filter-name>
     3         <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
     4         <init-param>
     5             <param-name>encoding</param-name>
     6             <param-value>UTF-8</param-value>
     7         </init-param>
     8     </filter>
     9 
    10     <filter-mapping>
    11         <filter-name>characterEncodingFilter</filter-name>
    12         <url-pattern>/*</url-pattern>
    13     </filter-mapping>

    在applicationContext.xml的权限配置部分,加入一条:

    /config/**=anon

    先将配置用户角色权限的路径设置为可匿名访问。

    然后还需要对DatabaseRealm中的代码稍加修改。

    DatabaseRealm.java

     1 public class DatabaseRealm extends AuthorizingRealm {
     2     @Autowired
     3     private RoleService roleService;
     4     @Autowired
     5     private PermissionService permissionService;
     6     @Autowired
     7     private UserService userService;
     8 
     9     protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
    10         //能进入到这里,表示账号已经通过认证了
    11         String username = (String) principals.getPrimaryPrincipal();
    12         //通过Dao获取角色和权限
    13 //       Set<String> permissions = new Dao().listPermissions(username);
    14 //       Set<String> roles = new Dao().listRoles(username);
    15         Set<String> roleNames = roleService.listRoleNames(username);
    16         Set<String> permisionNames = permissionService.listPermissions(username);
    17         //授权对象
    18         SimpleAuthorizationInfo sai =  new SimpleAuthorizationInfo();
    19         System.out.println("roles->:"+roleNames);
    20         System.out.println("perms->"+permisionNames);
    21         //把通过Dao获取到的角色和权限都放进去
    22         sai.setStringPermissions(permisionNames);
    23         sai.setRoles(roleNames);
    24         return sai;
    25 
    26     }
    27 
    28     protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
    29         //获取账号密码
    30         UsernamePasswordToken upt = (UsernamePasswordToken) token;
    31         String username = token.getPrincipal().toString();
    32         String password = new String(upt.getPassword());
    33         String encryptPassword = "";
    34         //获取数据库中的密码
    35 //        User user = new Dao().getUser(username);
    36 //        System.out.println("进到这里了:databaserealm");
    37         User user = userService.getByName(username);
    38         if(user != null) {
    39             String passwordInDB = user.getPassword();
    40             String salt = user.getSalt();
    41             //将传入的密码进行加盐
    42             encryptPassword = new SimpleHash("md5",password,user.getSalt(),2).toString();
    43             System.out.println("输入的密码:"+encryptPassword);
    44             System.out.println("passwordInDB"+user.getPassword());
    45         }
    46 
    47         //如果为空就是账号不存在,如果不相同就是密码错误,但是都抛出AuthenticationException,而不抛出具体错误原因,以防给破解者提供帮助信息
    48         if (null == user || !encryptPassword.equals(user.getPassword())) {
    49             throw new AuthenticationException();
    50         }
    51         //认证信息里存放账号和密码,getName()是当前Realm的继承方法,通常返回当前类名:DatabaseRealm
    52         SimpleAuthenticationInfo sai = new SimpleAuthenticationInfo(username,password,getName());
    53         return sai;
    54     }
    55 }

    将之前写的index.jsp稍加修改:

     1 <%@ page language="java" contentType="text/html; UTF-8" pageEncoding="UTF-8" isELIgnored="false" %>
     2 <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
     3 <head>
     4     <link rel="stylesheet" href="static/css/style.css"/>
     5 </head>
     6 
     7 <body>
     8 <div class="workingroom">
     9     <div class="loginDiv">
    10         ${request.contextPath}
    11         <c:if test="${!empty subject.principal}">
    12             <span>你好!${subject.principal}</span>
    13             <a href="doLogout">退出</a>
    14         </c:if>
    15         <c:if test="${empty subject.principal}">
    16             <a href="login">登录</a>
    17         </c:if>
    18     </div>
    19     <ul>
    20         <li><a href="listProduct">查看产品</a></li>
    21         <li><a href="deleteProduct">删除产品</a></li>
    22         <li><a href="deleteOrder">删除订单</a></li>
    23         <li><a href="config/listUser">用户管理</a></li>
    24     </ul>
    25 
    26 </div>
    27 </body>

    重启服务器,访问:http://localhost:8080/shiro/index

     到这里为止,我们的权限控制依然是由@RequiresRole,@RequiresPermission控制的,接下来对这个部分进行改造,通过动态配置url的方式完成权限控制。

    1.首先去掉之前在pageController中添加的权限角色注解

    2.在PermissionService中增加两个方法

    needInterceptor,listPermissionURLs

    在PermissionServiceImpl中的实现:

     @Override
        public boolean needInterceptor(String requestURI) {
            List<Permission> permissions = list();
            for (Permission permission : permissions) {
                if(permission.getUrl().equals(requestURI))
                    return true;
            }
            return false;
        }
    
        @Override
        public Set<String> listPermissionURLs(String username) {
            List<Role> roles = roleService.listRoles(username);
            Set<String> urls = new HashSet<>();
            List<RolePermission> rolePermissions = new ArrayList<>();
            for (Role role : roles) {
                RolePermissionExample example = new RolePermissionExample();
                example.createCriteria().andRidEqualTo(role.getId());
                List<RolePermission> temp = rolePermissionMapper.selectByExample(example);
                rolePermissions.addAll(temp);
            }
            for (RolePermission rolePermission : rolePermissions) {
                Permission permission = permissionMapper.selectByPrimaryKey(rolePermission.getPid());
                urls.add(permission.getUrl());
            }
            return urls;
        }

    3.URLPathMatchingFilter.java

    PathMatchingFilter是Shiro的内置过滤器,我们自定义一个URLPathMathingFilter继承这个过滤器。

    基本思路如下:

    1.如果没有登录,跳转到登录页面

    2.如果访问的路径不在权限系统中所维护,允许访问

    3.如果用户所属的角色没有当前路径的权限,不允许访问,跳转到/unauthorized,否则允许访问。

     1 public class URLPathMatchingFilter extends PathMatchingFilter {
     2     @Autowired
     3     PermissionService permissionService;
     4     @Override
     5     protected boolean onPreHandle(ServletRequest request, ServletResponse response, Object mappedValue) throws Exception {
     6         String requestURI = getPathWithinApplication(request);
     7         //判断是否登录
     8         Subject subject = SecurityUtils.getSubject();
     9         if (!subject.isAuthenticated()) {
    10             //如果没有登录,跳转到登录页面
    11             WebUtils.issueRedirect(request, response, "/login");
    12             return false;
    13         }
    14         //如果已经登录,判断是否是在Permission表中维护的路径
    15        if(!permissionService.needInterceptor(requestURI)) {
    16            //如果不是的话,允许访问
    17            return true;
    18        } else {
    19            //判断登录用户的角色是否拥有该路径的权限
    20            boolean hasPermission = false;
    21            String username = subject.getPrincipal().toString();
    22            Set<String> urls = permissionService.listPermissionURLs(username);
    23            for (String url : urls) {
    24              if(url.equals(requestURI)){
    25                  hasPermission = true;
    26                  break;
    27              }
    28            }
    29            if(hasPermission) {
    30                return true;
    31            } else {
    32                //权限不足
    33                UnauthorizedException ex = new UnauthorizedException("当前用户没有权限访问路径:" + requestURI);
    34                WebUtils.issueRedirect(request,response,"/authorized");
    35                return false;
    36            }
    37        }
    38     }
    39 }

    在Spring配置文件中声明URLPathMatchingFilter过滤器:

     1 <!--路径匹配过滤器--> 2 <bean id="urlfilter" class="com.vi.filter.URLPathMatchingFilter"/>

    在shiro过滤器工厂类中配置这个过滤器,设置过滤规则为所有url

    1  <property name="filters">
    2             <util:map>
    3                 <entry key="logout" value-ref="logoutFilter"/>
    4                 <entry key="url" value-ref="urlfilter"/>
    5             </util:map>
    6         </property>
     1 public class URLPathMatchingFilter extends PathMatchingFilter {
     2     @Autowired
     3     PermissionService permissionService;
     4     @Override
     5     protected boolean onPreHandle(ServletRequest request, ServletResponse response, Object mappedValue) throws Exception {
     6         String requestURI = getPathWithinApplication(request);
     7         System.out.println("debug:"+requestURI);
     8         //判断是否登录
     9         Subject subject = SecurityUtils.getSubject();
    10         if (!subject.isAuthenticated()) {
    11             //如果没有登录,跳转到登录页面
    12             WebUtils.issueRedirect(request, response, "/login");
    13             return false;
    14         }
    15         //如果已经登录,判断是否是在Permission表中维护的路径
    16        if(!permissionService.needInterceptor(requestURI)) {
    17            //如果不是的话,允许访问
    18            return true;
    19        } else {
    20            //判断登录用户的角色是否拥有该路径的权限
    21            boolean hasPermission = false;
    22            String username = subject.getPrincipal().toString();
    23            Set<String> urls = permissionService.listPermissionURLs(username);
    24            for (String url : urls) {
    25              if(url.equals(requestURI)){
    26                  hasPermission = true;
    27                  break;
    28              }
    29            }
    30            if(hasPermission) {
    31                return true;
    32            } else {
    33                //权限不足
    34                UnauthorizedException ex = new UnauthorizedException("当前用户没有权限访问路径:" + requestURI);
               subject.getSession().setAttribte("ex",ex);
    35 WebUtils.issueRedirect(request,response,"/unauthorized"); 36 return false; 37 } 38 } 39 } 40 }

    完成以后,重启tomcat,接下来就可以动态的对访问权限进行控制了。

    我们可以把用户管理,角色管理,权限管理所对应的路径全部赋给admin。这样角色不是admin的就不能够访问了。

  • 相关阅读:
    <Android 应用 之路> 聚合数据SDK
    AngularJS所有版本下载地址
    <Android 应用 之路> 天气预报(三)
    <Android 应用 之路> 天气预报(二)
    Java集合框架—Set
    HBase数据模型(2)
    HBase数据模型(1)
    ESP8266串口WiFi扩展板详解
    Arduino ESP8266编程深入要点
    <Android Framework 之路>多线程
  • 原文地址:https://www.cnblogs.com/blogforvi/p/11683319.html
Copyright © 2011-2022 走看看