快速搭建shiro框架

作者: WhyNotYue | 来源:发表于2017-04-08 17:05 被阅读214次

    一,shiro简介


    维基百科:Apache Shiro(读作“sheeroh”,即日语“”)是一个开源安全框架,提供身份验证授权密码学会话管理。Shiro框架直观、易用,同时也能提供健壮的安全性。


    二,快速搭建


    1. 导包(利用Maven)

        <properties>
            <!--shiro版本号-->
            <shiro.version>1.4.0-RC2</shiro.version>
        </properties>
    
        <dependencies>
            <!-- shiro -->
            <dependency>
                <groupId>org.apache.shiro</groupId>
                <artifactId>shiro-core</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-spring</artifactId>
                <version>${shiro.version}</version>
            </dependency>
        <dependencies>
    

    2.建表(数据库采用myBatis)

    create table `t_user` (
        `id` int (11),
        `userName` varchar (60),
        `password` varchar (300),
        `roleId` int (11)
    ); 
    insert into `t_user` (`id`, `userName`, `password`, `roleId`) values('1','ayue','123456','1');
    insert into `t_user` (`id`, `userName`, `password`, `roleId`) values('2','aaa','12345','2');
    insert into `t_user` (`id`, `userName`, `password`, `roleId`) values('3','bbb','12345',NULL);
    insert into `t_user` (`id`, `userName`, `password`, `roleId`) values('4','ccc','12345',NULL);
    
    create table `t_role` (
        `id` int (11),
        `roleName` varchar (60)
    ); 
    insert into `t_role` (`id`, `roleName`) values('1','admin');
    insert into `t_role` (`id`, `roleName`) values('2','teacher');
    
    create table `t_permission` (
        `id` int (11),
        `permissionName` varchar (150),
        `roleId` int (11)
    ); 
    insert into `t_permission` (`id`, `permissionName`, `roleId`) values('1','user:*','1');
    insert into `t_permission` (`id`, `permissionName`, `roleId`) values('2','student:*','2');
    

    3.建立3个实体类

    package domain;
    
    /**
     * Created by 越 on 2017/4/4.
     */
    public class User {
        private Integer id;
    
        private String userName;
    
        private String password;
    
        private Integer roleId;
    
        public Integer getId() {
            return id;
        }
    
        public void setId(Integer 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 Integer getRoleId() {
            return roleId;
        }
    
        public void setRoleId(Integer roleId) {
            this.roleId = roleId;
        }
    }
    
    package domain;
    
    /**
     * Created by 越 on 2017/4/4.
     */
    public class Role {
        private int id;
        private String roleName;
    
        public int getId() {
            return id;
        }
    
        public void setId(int id) {
            this.id = id;
        }
    
        public String getRoleName() {
            return roleName;
        }
    
        public void setRoleName(String roleName) {
            this.roleName = roleName;
        }
    }
    
    
    package domain;
    
    /**
     * Created by 越 on 2017/4/4.
     */
    public class Permission {
        private int id;
        private String permissionName;
        private int roleId;
    
        public int getId() {
            return id;
        }
    
        public void setId(int id) {
            this.id = id;
        }
    
        public String getPermissionName() {
            return permissionName;
        }
    
        public void setPermissionName(String permissionName) {
            this.permissionName = permissionName;
        }
    
        public int getRoleId() {
            return roleId;
        }
    
        public void setRoleId(int roleId) {
            this.roleId = roleId;
        }
    }
    
    

    4. 配置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="dao.UserDao">
        <resultMap id="BaseResultMap" type="domain.User">
            <result property="id" column="id"/>
            <result property="userName" column="userName"/>
            <result property="password" column="password"/>
            <result property="roleId" column="roleId"/>
        </resultMap>
    
        <sql id="Base_Column_List">
        id, username, password,roleId
        </sql>
    
        <select id="findUserByUsername" parameterType="String" resultMap="BaseResultMap">
            select
            <include refid="Base_Column_List"/>
            from t_user where userName=#{userName}
        </select>
    
        <select id="findRoles" parameterType="String" resultType="String">
        select r.roleName from t_user u,t_role r where u.roleId=r.id and u.userName=#{userName}
      </select>
    
        <select id="findPermissions" parameterType="String" resultType="String">
        select p.permissionName from t_user u,t_role r,t_permission p
        where u.roleId=r.id and p.roleId=r.id and u.userName=#{userName}
      </select>
    
    </mapper>
    

    5. 建立自定义的MyRealm类:用于处理自己的业务逻辑

    package shiro;
    
    import domain.User;
    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.authz.AuthorizationInfo;
    import org.apache.shiro.authz.SimpleAuthorizationInfo;
    import org.apache.shiro.realm.AuthorizingRealm;
    import org.apache.shiro.subject.PrincipalCollection;
    import service.UserService;
    
    import javax.annotation.Resource;
    import java.util.Set;
    
    /**
     * Created by 越 on 2017/4/5.
     */
    public class MyRealm extends AuthorizingRealm{
    
        @Resource
        private UserService userService;
    
        /**
         * 用于权限的认证
         * @param principalCollection
         * @return
         */
        protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
            String username = principalCollection.getPrimaryPrincipal().toString();
            SimpleAuthorizationInfo info = new SimpleAuthorizationInfo() ;
            Set<String> roleName = userService.findRoles(username);
            Set<String> permissions = userService.findPermissions(username);
            info.setRoles(roleName);
            info.setStringPermissions(permissions);
            return info;
        }
    
        /**
         * 登录验证(先执行)
         * @param token
         * @return
         * @throws AuthenticationException
         */
        protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
            // 获取用户账号
            String username = token.getPrincipal().toString();
            // 从数据库中查询用户信息
            User user = userService.findUserByUsername(username);
            if (user != null){
                // 将查询到的用户名和密码存放到authenticationInfo用于后面的权限判断。第三个参数传入realName。
                System.out.println(getName());
                AuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(user.getUserName(),user.getPassword(),getName());
                return authenticationInfo;
            }else
                return null;
        }
    }
    

    6. 与SSM整合

    关于如何搭建SSM框架:SSM框架——详细整合教程(Spring+SpringMVC+MyBatis)


    1. 配置spring-mybatis.xml
    <!-- Shiro过滤器 核心-->
        <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
            <!-- Shiro的核心安全接口,这个属性是必须的 -->
            <property name="securityManager" ref="securityManager"/>
            <!-- 身份认证失败,则跳转到登录页面的配置 -->
            <property name="loginUrl" value="/jsp/login.jsp"/>
            <!-- 权限认证失败,则跳转到指定页面 -->
            <property name="unauthorizedUrl" value="/jsp/nopower.jsp"/>
            <!-- Shiro连接约束配置,即过滤链的定义 -->
            <property name="filterChainDefinitions">
                <value>
                    <!--anon 表示匿名访问,不需要认证以及授权-->
                    /user/loginAdmin=anon
    
                    <!--authc表示需要认证 没有进行身份认证是不能进行访问的-->
                    /user/admin*=authc
    
                    <!--表示访问/student请求的用户必须是teacher角色,不然是不能进行访问的。-->
                    /user/student=roles[teacher]
                    <!--表示访问/teacher请求是需要当前用户具有user:create权限才能进行访问的。-->
                    /user/teacher=perms["user:create"]
                </value>
            </property>
        </bean>
    
        <!-- 保证实现了Shiro内部lifecycle函数的bean执行 -->
        <bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/>
    
        <!-- 开启Shiro注解 -->
        <bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"
              depends-on="lifecycleBeanPostProcessor"/>
        <bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">
            <property name="securityManager" ref="securityManager"/>
        </bean>
    

    2. UserController
    package controller;
    import domain.User;
    import org.apache.shiro.SecurityUtils;
    import org.apache.shiro.authc.UsernamePasswordToken;
    import org.apache.shiro.subject.Subject;
    import org.springframework.stereotype.Controller;
    import org.springframework.ui.Model;
    import org.springframework.web.bind.annotation.RequestMapping;
    import service.UserService;
    import javax.annotation.Resource;
    import javax.servlet.http.HttpServletRequest;
    /**
     * Created by 越 on 2017/3/29.
     */
    @Controller
    @RequestMapping("/user")
    public class UserController {
        @Resource
        private UserService userService;
        @RequestMapping("/loginAdmin")
        public String login(User user,Model model){
            Subject subject = SecurityUtils.getSubject();
            UsernamePasswordToken token = new UsernamePasswordToken(user.getUserName(),user.getPassword());
            try{
                subject.login(token);
                return "admin";
            }catch (Exception e){
                model.addAttribute("error","用户名或密码错误!");
                return "login";
            }
        }
    
        @RequestMapping("/admin")
        public String admin(){
            return "admin";
        }
    
        @RequestMapping("/student")
        public String student(){
            return "student";
        }
    
        @RequestMapping("/teacher")
        public String teacher(){
            return "teacher";
        }
    
    }
    

    3. 页面

    login.jsp

    <%--
      Created by IntelliJ IDEA.
      User: 越
      Date: 2017/4/8
      Time: 15:03
      To change this template use File | Settings | File Templates.
    --%>
    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
        <title>登录页面</title>
    </head>
    <body>
    <form method="post" action="/user/loginAdmin">
        用户名:<input type="text" name="userName"/><br>
        密码:<input type="password" name="password"/><br>
        <input type="submit" value="登录"/>
    </form>
    </body>
    </html>
    

    admin.jsp

    <%--
      Created by IntelliJ IDEA.
      User: 越
      Date: 2017/3/29
      Time: 17:09
      To change this template use File | Settings | File Templates.
    --%>
    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <%@ taglib prefix="shiro" uri="http://shiro.apache.org/tags" %>
    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
    <html>
    <head>
        <title>后台</title>
    </head>
    
    <body>
    <%--具有admin角色才会显示标签内的信息。--%>
    <shiro:hasRole name="admin">
        这是admin角色登录:<shiro:principal></shiro:principal>
    </shiro:hasRole>
    <br>
    <%--用户拥有user:create这个权限才回显示--%>
    <shiro:hasPermission name="user:create">
        有user:create权限信息
    </shiro:hasPermission>
    <br>
    登录成功
    </body>
    </html>
    

    teacher.jsp

    <%--
      Created by IntelliJ IDEA.
      User: 越
      Date: 2017/4/8
      Time: 16:50
      To change this template use File | Settings | File Templates.
    --%>
    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
        <title>教师</title>
    </head>
    <body>
    访问teacher成功
    </body>
    </html>
    
    

    student.jsp

    <%--
      Created by IntelliJ IDEA.
      User: 越
      Date: 2017/4/8
      Time: 16:50
      To change this template use File | Settings | File Templates.
    --%>
    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
        <title>学生</title>
    </head>
    <body>
    访问student成功
    </body>
    </html>
    
    

    nopower.jsp

    <%--
      Created by IntelliJ IDEA.
      User: 越
      Date: 2017/4/8
      Time: 15:23
      To change this template use File | Settings | File Templates.
    --%>
    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
        <title>权限认证失败</title>
    </head>
    <body>
    权限认证失败
    </body>
    </html>
    

    4. web.xml
    <!--shiro过滤器定义 -->
        <filter>
            <filter-name>shiroFilter</filter-name>
            <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
            <init-param>
                <!-- 该值缺省为false,表示生命周期由SpringApplicationContext管理,设置为true则表示由ServletContainer管理 -->
                <param-name>targetFilterLifecycle</param-name>
                <param-value>true</param-value>
            </init-param>
        </filter>
        <filter-mapping>
            <filter-name>shiroFilter</filter-name>
            <url-pattern>/*</url-pattern>
        </filter-mapping>
    

    7. 演示

    1. 登录:


      Paste_Image.png
    2. 因为ayue是admin角色,且拥有user:create权限,故进入后台页面:


      Paste_Image.png
    3. 访问/user/teacher


      Paste_Image.png
    4. 访问/user/student


      Paste_Image.png

      3和4的原因在于在spring-mybatis.xml中我们的配置:

    <!--表示访问/student请求的用户必须是teacher角色,不然是不能进行访问的。-->
     /user/student=roles[teacher]
     <!--表示访问/teacher请求是需要当前用户具有user:create权限才能进行访问的。-->
     /user/teacher=perms["user:create"]
    

    参考资料:SSM(三)Shiro使用详解

    相关文章

      网友评论

        本文标题:快速搭建shiro框架

        本文链接:https://www.haomeiwen.com/subject/rkwlattx.html