プロジェクト実録のシロの使用


本文を読む前に、まず次の2つの文章を読むことをお勧めします.
  • プロジェクト実録のMaven工事構築
  • プロジェクト実録の統合Spring MVC
  • プロジェクト実録の統合Mybatis
  • 一、関連Jarパッケージを追加する    
    プロジェクトpom.xmlに次の依存度を追加します.     
    <dependency>
                <groupId>taglibs</groupId>
                <artifactId>standard</artifactId>
                <version>1.1.2</version>
                <type>jar</type>
            </dependency>
            <!-- SECURITY begin -->
                <dependency>
                    <groupId>org.apache.shiro</groupId>
                    <artifactId>shiro-core</artifactId>
                    <version>${shiro.version}</version>
                </dependency>
                <dependency>
                    <groupId>org.apache.shiro</groupId>
                    <artifactId>shiro-spring</artifactId>
                    <version>${shiro.version}</version>
                </dependency>
                <dependency>
                    <groupId>org.apache.shiro</groupId>
                    <artifactId>shiro-web</artifactId>
                    <version>${shiro.version}</version>
                </dependency>
                <dependency>
                    <groupId>org.apache.shiro</groupId>
                    <artifactId>shiro-ehcache</artifactId>
                    <version>${shiro.version}</version>
                </dependency>
                <!-- SECURITY end -->

     
    二、データベーステーブルとデータは3つのテーブルが必要です.userはユーザーを表し、複数の異なる権限のユーザーを初期化します.menuはメニューを表し、異なるユーザーが異なるメニューを持っている.user_menuは、ここでマークされるメニューを持つユーザーとメニューの対照表です.実際の開発者は通常、ロールベースで権限管理を行いますが、便宜上、この例はユーザーベースです.
     
    CREATE TABLE `user` (
      `id` bigint(20) NOT NULL AUTO_INCREMENT,
      `username` varchar(20) NOT NULL,
      `password` varchar(20) NOT NULL,
      PRIMARY KEY (`id`,`username`)
    ) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8
    CREATE TABLE `menu` (
      `id` bigint(20) NOT NULL AUTO_INCREMENT,
      `name` varchar(20) NOT NULL,
      PRIMARY KEY (`id`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8
    CREATE TABLE `user_menu` (
      `id` bigint(20) NOT NULL AUTO_INCREMENT,
      `user_id` bigint(20) NOT NULL,
      `menu_id` bigint(20) NOT NULL,
      PRIMARY KEY (`id`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8
    INSERT INTO USER (id,username,PASSWORD) VALUES (1,'jobs','qwe123')
    INSERT INTO USER (id,username,PASSWORD) VALUES (2,'gates','888888')
    INSERT INTO menu (id,NAME) VALUES (1,'   ')
    INSERT INTO menu (id,NAME) VALUES (2,'   ')
    INSERT INTO menu (id,NAME) VALUES (3,'   ')
    INSERT INTO menu (id,NAME) VALUES (4,'   ')
    INSERT INTO menu (id,NAME) VALUES (5,'   ')
    INSERT INTO user_menu (id,user_id,menu_id) VALUES (1,1,1)
    INSERT INTO user_menu (id,user_id,menu_id) VALUES (2,1,2)
    INSERT INTO user_menu (id,user_id,menu_id) VALUES (3,1,3)
    INSERT INTO user_menu (id,user_id,menu_id) VALUES (4,2,3)
    INSERT INTO user_menu (id,user_id,menu_id) VALUES (4,2,4)
    INSERT INTO user_menu (id,user_id,menu_id) VALUES (4,2,5)

     
    私たちはjobsとgatesの2人のユーザーがいて、メニュー1、メニュー2、メニュー3、メニュー4とメニュー5の5つのメニューがあります.jobsはメニュー1、メニュー2、メニュー3、gatesはメニュー3、メニュー4、メニュー5を持っている.三、関連コード1を作成し、dao層にwang.wangci.bottae.dao.entity.Menuクラスを新規作成する  
    package wang.wangci.bottae.dao.entity;
    public class Menu {
        private long id;
        private String name;
        public long getId() {
            return id;
        }
        public void setId(long id) {
            this.id = id;
        }
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        
        
    }

     2、dao層のUserクラスを修正する
     
    package wang.wangci.bottae.dao.entity;
    import java.util.ArrayList;
    import java.util.List;
    public class User {
        private long id;
        private String username;
        private String password;
        private List<Menu> menuList= new ArrayList<Menu>();
        public long getId() {
            return id;
        }
        public void setId(long id) {
            this.id = id;
        }
        public String getUsername() {
            return username;
        }
        public void setUsername(String username) {
            this.username = username;
        }
        public String getPassword() {
            return password;
        }
        public void setPassword(String password) {
            this.password = password;
        }
        public List<Menu> getMenuList() {
            return menuList;
        }
        public void setMenuList(List<Menu> menuList) {
            this.menuList = menuList;
        }
        
    }

     
    3、dao層で新規作成 wang.wangci.bottae.dao.entity.UserMenuクラス
     
    package wang.wangci.bottae.dao.entity;
    public class UserMenu {
        private long id;
        private long userId;
        private long menuId;
        public long getId() {
            return id;
        }
        public void setId(long id) {
            this.id = id;
        }
        public long getUserId() {
            return userId;
        }
        public void setUserId(long userId) {
            this.userId = userId;
        }
        public long getMenuId() {
            return menuId;
        }
        public void setMenuId(long menuId) {
            this.menuId = menuId;
        }
        
    }

     
    4、dao層にwang.wangci.bottae.dao.mapper.MenuMapperを新規作成する
     
    package wang.wangci.bottae.dao.mapper;
    import java.util.List;
    import org.apache.ibatis.annotations.Param;
    import wang.wangci.bottae.dao.entity.Menu;
    public interface MenuMapper {
        public List<Menu> selectsByUserId(@Param("userId")long userId);
    }

     
    4、UserMapperインタフェースの修正
     
    package wang.wangci.bottae.dao.mapper;
    import java.util.List;
    public interface UserMapper {
        public List<User> selects();
        
        public User selectById(@Param("id")long id);
        
        public User selectByName(@Param("name")String name); 
    }

     
    5、UserMapper.xmlの修正
     
    <?xml version="1.0" encoding="UTF-8" ?>  
    <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    <mapper namespace="wang.wangci.bottae.dao.mapper.UserMapper">
            
        <select id="selects" resultType="wang.wangci.bottae.dao.entity.User">
            SELECT *    FROM user
        </select>
        <select id="selectById" resultType="wang.wangci.bottae.dao.entity.User">
            SELECT *    FROM user WHERE id=#{id}
        </select>
        
        <select id="selectByName" resultType="wang.wangci.bottae.dao.entity.User">
            SELECT *    FROM user WHERE username=#{name}
        </select>
    </mapper>

     
    6、新しいMenuMapper.xml    
     
    <?xml version="1.0" encoding="UTF-8" ?>  
    <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" 
    "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    <mapper namespace="wang.wangci.bottae.dao.mapper.MenuMapper">
            
        <select id="selectsByUserId" resultType="wang.wangci.bottae.dao.entity.Menu">
            SELECT 
            m.id,
            m.name
            FROM 
            menu m,
            user_menu u
            WHERE m.id = u.menu_id AND u.user_id=#{userId}
        </select>
    </mapper>

     
    7、サービス層がUserServiceインタフェースを修正する
     
    package wang.wangci.bottae.service;
    import java.util.List;
    import wang.wangci.bottae.dao.entity.User;
    public interface UserService {
        public List<User> finds();
        
        public User findById(long id);
        
        public User findByName(String name);
    }
     
    8、service   UserServiceImpl 
     
    package wang.wangci.bottae.service.impl;
    import java.util.List;
    @Component
    public class UserServiceImpl implements UserService {
        
        @Resource
        private UserMapper userMapper;
        @Override
        public List<User> finds() {
            return userMapper.selects();
        }
        @Override
        public User findById(long id) {
            return userMapper.selectById(id);
        }
        @Override
        public User findByName(String name) {
            return userMapper.selectByName(name);
        }
    }

     
    9、サービス層の新しいMenuServiceインタフェース
     
    package wang.wangci.bottae.service;
    import java.util.List;
    import wang.wangci.bottae.dao.entity.Menu;
    public interface MenuService {
        public List<Menu> findsByUserId(long userId);
    }

     
    10、サービス新規MenuServiceImpl実装クラス
     
    package wang.wangci.bottae.service.impl;
    import java.util.List;
    import javax.annotation.Resource;
    import org.springframework.stereotype.Component;
    import wang.wangci.bottae.dao.entity.Menu;
    import wang.wangci.bottae.dao.mapper.MenuMapper;
    import wang.wangci.bottae.service.MenuService;
    @Component
    public class MenuServiceImpl implements MenuService{
        
        @Resource
        private MenuMapper menuMapper;
        @Override
        public List<Menu> findsByUserId(long userId) {
            return menuMapper.selectsByUserId(userId);
        }
    }

     
    11、web層の新しいLoginControlクラス  注意:サンプルコードは厳密ではありません.実際の開発で使用する場合は、各種の異常処理を行ってください.
     
    package wang.wangci.bottae.web.controllers;
    import java.util.List;
    @Controller
    public class LoginController {
        
        @Resource
        private UserService userService;
        @Resource
        private MenuService menuService;
        
        @RequestMapping("/")
        public String index(String passwd,HttpServletRequest request, HttpServletResponse response,ModelMap model){
            String username = (String)request.getSession().getAttribute("username");
            User user = userService.findByName(username);
            if(user!=null){
                List<Menu> menus = menuService.findsByUserId(user.getId());
                model.addAttribute("menus", menus);
            }
            return "index";
        }
        
        @RequestMapping(value = "/login", method = {RequestMethod.GET,RequestMethod.POST})
        public String login(@RequestParam(value="username",defaultValue="",required=false)String username,
                @RequestParam(value="passwd",defaultValue="",required=false)String passwd,
                HttpServletRequest request, HttpServletResponse response, ModelMap model)throws Exception {
            
            UsernamePasswordToken token = new UsernamePasswordToken(username,passwd);
            Subject subject = SecurityUtils.getSubject();
            try {
                subject.login(token);
            }catch (UnknownAccountException uae) {
                model.addAttribute("message", "     ,     ");
            }catch (IncorrectCredentialsException ice) {
                model.addAttribute("message", "    ,     ");
            } catch (DisabledAccountException e) {
                model.addAttribute("message", "      ,    ,        !");
            }
            
            if(subject.isAuthenticated()){
                HttpSession session = request.getSession();
                session.setAttribute("username", username);
                return "redirect:/";
            }else{
                token.clear();
            }
            return "login";
            
        }
        
        @RequestMapping("/logout")
        public String logout(HttpServletRequest request,HttpServletResponse response,ModelMap model){
            SecurityUtils.getSubject().logout();
            return "redirect:/login";
        }
    }

     
     12、web層新規HasAnyPermissionsTag類
     
    package wang.wangci.bottae.web.security;
    import org.apache.shiro.subject.Subject;
    public class HasAnyPermissionsTag extends PermissionTag{
        private static final long serialVersionUID = 1L;
        private static final String PERMISSION_NAMES_DELIMETER = ",";
        @Override
        protected boolean showTagBody(String permissionNames) {
            boolean hasAnyPermission = false;
            Subject subject = getSubject();
            if (subject != null) {
                for (String permission : permissionNames
                        .split(PERMISSION_NAMES_DELIMETER)) {
                    if (subject.isPermitted(permission.trim())) {
                        hasAnyPermission = true;
                        break;
                    }
                }
            }
            return hasAnyPermission;
        }
    }

     
    13、web層新規Principalクラス
     
    package wang.wangci.bottae.web.security;
    import java.io.Serializable;
    public class Principal implements Serializable{
        private static final long serialVersionUID = 1L;
        
        private long id; //   
        private String name; //   
        
        public Principal(User user) {
            this.id = user.getId();
            this.name = user.getUsername();
        }
        public long getId() {
            return id;
        }
        public void setId(long id) {
            this.id = id;
        }
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        
        
        
    }

     
    14、web層新規SystemAuthorizingRealmクラス
     
    package wang.wangci.bottae.web.security;
    import java.util.List;
    public class SystemAuthorizingRealm extends AuthorizingRealm {
        private static final Logger logger = LoggerFactory
                .getLogger(SystemAuthorizingRealm.class);
        @Resource
        private UserService userService;
        @Resource
        private MenuService menuService;
        /**
         *       ,      
         */
        @Override
        protected AuthenticationInfo doGetAuthenticationInfo(
                AuthenticationToken authcToken) {
            UsernamePasswordToken token = (UsernamePasswordToken) authcToken;
            //        
            User user = null;
            try {
                user = userService.findByName(token.getUsername());
            } catch (Exception e) {
                e.printStackTrace();
            }
            if (user != null) {
                
                return new SimpleAuthenticationInfo(new Principal(user),
                        user.getPassword(), getName());
            } else {
                return null;
            }
        }
        /**
         *         ,                    
         */
        @Override
        protected AuthorizationInfo doGetAuthorizationInfo(
                PrincipalCollection principals) {
            Principal principal = (Principal) getAvailablePrincipal(principals);
            User user = null;
            try {
                user = userService.findByName(principal.getName());
            } catch (Exception e) {
                logger.info("         ",e);
            }
            if (user != null) {
                SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
                //          
                List<Menu> list = menuService.findsByUserId(user.getId());
                
                for (Menu menu : list) {
                        //     Permission     
                        info.addStringPermission(menu.getName());
                }
                //       
                info.addStringPermission("user");
                //         
                return info;
            } else {
                return null;
            }
        }
    }

     
    15、resources/contextの下でcontext-shiro.xmlファイルを新規作成する
     
    <?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-3.2.xsd"
        default-lazy-init="true">
        <description>Shiro    </description>
        
        <!--       Realm -->
        <bean id="shiroDbRealm" class="wang.wangci.bottae.web.security.SystemAuthorizingRealm" >
        </bean>
        
        <!-- Shiro Filter -->
        <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
            <property name="securityManager" ref="securityManager" />
            <property name="loginUrl" value="/login" />
            <property name="successUrl" value="/" />
            <property name="unauthorizedUrl" value="/logout" />
            <property name="filterChainDefinitions">
                <value>
                    /login = anon
                    /logout = logout
                    /static/** = anon
                    /** = authc
                </value>
            </property>
        </bean>
        <!--       Cache,   EhCache -->
        <bean id="shiroEhcacheManager" class="org.apache.shiro.cache.ehcache.EhCacheManager">
            <!-- <property name="cacheManagerConfigFile" value="classpath:security/ehcache-shiro.xml"/> -->
            <!-- <property name="cacheManager" ref="cacheManagerFactory" /> -->
        </bean>
        
        <!-- Shiro's main business-tier object for web-enabled applications -->
        <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
            <property name="realm" ref="shiroDbRealm" />
            <property name="cacheManager" ref="shiroEhcacheManager" />
        </bean>
        
        
        <!--      Shiro  lifecycle   bean   -->
        <bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/>
        
        <!-- AOP          -->
        <bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator" depends-on="lifecycleBeanPostProcessor">
            <property name="proxyTargetClass" value="true" />
        </bean>
        <bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">
            <property name="securityManager" ref="securityManager"/>
        </bean>
    </beans>

      16.WEB-INFの下にディレクトリtldsを新規作成し、tldsディレクトリの下にファイルshiros-ext.tldを新規作成する
     
    <?xml version="1.0" encoding="UTF-8" ?>
    <!-- shiro       -->
    <!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN"
      "http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd">
    <taglib>
        <tlib-version>1.1.2</tlib-version>
        <jsp-version>1.2</jsp-version>
        <short-name>Apache Shiro</short-name>
        <uri>http://shiro.apache.org/tagss</uri>
        <description>Apache Shiro JSP Tag Library extends the hasAnyPermissions
            tag.</description>
        <tag>
            <name>hasAnyPermissions</name>
            <tag-class>wang.wangci.bottae.web.security.HasAnyPermissionsTag</tag-class>
            <body-content>JSP</body-content>
            <description>Displays body content only if the current user has one of
                the specified permissions from a
                comma-separated list of permission
                names.
            </description>
            <attribute>
                <name>name</name>
                <required>true</required>
                <rtexprvalue>true</rtexprvalue>
            </attribute>
        </tag>
    </taglib>

     17.viewsディレクトリの西にincludeフォルダを新規作成し、includeの下にtaglib.jspを新規作成する
     
    <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
    <%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
    <%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt"%>
    <%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions"%>
    <%@ taglib prefix="shiro" uri="http://shiro.apache.org/tags"%>
    <%@ taglib prefix="shiro-ext" uri="/WEB-INF/tlds/shiros-ext.tld"%>
    <c:set var="ctx" value="${pageContext.request.contextPath}" />
    <c:set var="ctxStatic" value="${pageContext.request.contextPath}/static" />

     18、viewsの下でlogin.jspファイルを新規作成する
     
    <%@ page language="java" pageEncoding="UTF-8"%>
    <!DOCTYPE HTML>
    <html lang="zh-CN">
    <head>
    <meta charset="UTF-8">
    <title>UUID</title>
    </head>
    <body>
        <form action="/login">
               :<input type="text" name='username'>
              :<input type='password' name='passwd'>
            
            <input type="submit" value="  ">
        </form>
    </body>
    </html>

     19.viewsディレクトリの下にindex.jspファイルを新規作成する
     
    <%@ page language="java" pageEncoding="UTF-8"%>
    <%@ include file="/WEB-INF/views/include/taglib.jsp"%>
    <!DOCTYPE HTML>
    <html lang="zh-CN">
    <head>
    <meta charset="UTF-8">
    <title>UUID</title>
    </head>
    <body>
      ,${username},        !<br>
            <shiro-ext:hasAnyPermissions name="   ">
                   <br>
            </shiro-ext:hasAnyPermissions>
            <shiro-ext:hasAnyPermissions name="   ">
                   <br>
            </shiro-ext:hasAnyPermissions>
            <shiro-ext:hasAnyPermissions name="   ">
                   <br>
            </shiro-ext:hasAnyPermissions>
            <shiro-ext:hasAnyPermissions name="   ">
                   <br>
            </shiro-ext:hasAnyPermissions>
            <shiro-ext:hasAnyPermissions name="   ">
                   <br>
            </shiro-ext:hasAnyPermissions>
            
            <a href="/logout">    </a>
    </body>
    </html>

     
    20、web.xmlにブロック構成を追加する
           
      <!-- Shiro Security filter -->  
          
        <filter>  
            <filter-name>shiroFilter</filter-name>  
            <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>  
        </filter>  
        <filter-mapping>  
            <filter-name>shiroFilter</filter-name>  
            <url-pattern>/*</url-pattern>  
            <dispatcher>REQUEST</dispatcher>  
            <dispatcher>FORWARD</dispatcher>  
        </filter-mapping>

     
     四、運行テスト
    コンパイル実行サービス.ブラウザ入力:localhost:7777は、ログインページにブロックされます.ログインページにjobsパスワードqwe 123を入力し、ログインし、jobsがメニュー1、メニュー2、メニュー3を持っていることを表示したら、説明に成功したので、クリックしてログインを終了し、gates/888888を使用してログインし、所有メニュー3、メニュー4、メニュー5を表示したら説明に成功した. 
    本明細書のソース:
    360クラウドダウンロード アクセスパスワード0385
    私のブログに入って原文を見てください.