zoukankan      html  css  js  c++  java
  • Shiro——认证

    引入shiro依赖

            <!-- shiro -->
            <dependency> <!-- shiro-core Required in all environments. -->
                <groupId>org.apache.shiro</groupId>
                <artifactId>shiro-core</artifactId>
                <version>${shiro.version}</version>
            </dependency>
            <dependency> <!-- Enables support for web-based applications. -->
                <groupId>org.apache.shiro</groupId>
                <artifactId>shiro-web</artifactId>
                <version>${shiro.version}</version>
            </dependency>
            <dependency> <!-- Enables AspectJ support for Shiro AOP and Annotations. -->
                <groupId>org.apache.shiro</groupId>
                <artifactId>shiro-aspectj</artifactId>
                <version>${shiro.version}</version>
            </dependency>
            <dependency> <!-- Enables Spring Framework integration. -->
                <groupId>org.apache.shiro</groupId>
                <artifactId>shiro-spring</artifactId>
                <version>${shiro.version}</version>
            </dependency>
            <!-- -->

    web.xml中添加ShiroFilter

    • Shiro 提供了与 Web 集成的支持,其通过一个ShiroFilter 入口来拦截需要安全控制的URL,然后进行相应的控制
    • ShiroFilter 类似于如 Strut2/SpringMVC 这种web 框架的前端控制器,是安全控制的入口点,其负责读取配置(如ini 配置文件),然后判断URL是否需要登录/权限等工作。、
    • DelegatingFilterProxy 作用是自动到 Spring 容器查找名字为 shiroFilter(filter-name)的 bean 并把所有 Filter的操作委托给它。
     <!-- Shiro Filter is defined in the spring application context: -->
        <filter>
            <filter-name>shiroFilter</filter-name>
            <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
            <init-param>
                <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>

    spring核心配置文件中配置shiro

       <!-- 自定义Realm -->
        <bean id="JdbcRealm" class="com.nchu.shiro.JdbcRealm" ></bean>
    
        <!-- 安全管理器 -->
        <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
            <property name="realm" ref="JdbcRealm"/>
        </bean>
    
        <!-- shiroFilter /pub/** = anon -->
        <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
            <property name="loginUrl" value="/shiro/login.jsp" />
            <property name="successUrl" value="/shiro/list.jsp"/>
            <property name="unauthorizedUrl" value="/shiro/unauthorized.jsp"/>
            <property name="securityManager" ref="securityManager"/>
            <!--1).anon可以被匿名访问
                2).authc被认证后可被访问,没有认证会被重定向到loginUrl指定的页面
                3).logout登出-->
            <property name="filterChainDefinitions">
                <value>
                    /login       = anon
                    /shiro/login = anon
                    /shiro/logout=logout
                    /**          = authc
                </value>
            </property>
        </bean>
    
        <!-- Shiro生命周期处理器-->
        <bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/>

    身份验证

    • 身份验证:一般需要提供如身份 ID 等一些标识信息来表明登录者的身份,如提供 email,用户名/密码来证明。
    • 在 shiro 中,用户需要提供 principals (身份)和 credentials(证明)给 shiro,从而应用能验证用户身份:
    • principals:身份,即主体的标识属性,可以是任何属性,如用户名、邮箱等,唯一即可。一个主体可以有多个 principals,但只有一个Primary principals,一般是用户名/邮箱/手机号。
    • credentials证明/凭证,即只有主体知道的安全值,如密码/数字证书等。
    • 最常见的 principals 和 credentials 组合就是用户名/密码

    Shiro 认证流程

    1、前端请求

      1). 创建一个表单页面:login.jsp

    <%--
      Created by IntelliJ IDEA.
      User: root
      Date: 2018/1/16 0016
      Time: 19:16
      To change this template use File | Settings | File Templates.
    --%>
    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
        <title>Title</title>
    </head>
    <body>
    <h2>Login Page</h2>
    
    <form action="${pageContext.request.contextPath}/shiro/login" method="post">
        UserName : <input type="text" name="username">
        <br><br>
        PassWord : <input type="password" name="password">
        <br><br>
        <input type="submit" value="登录">
    </form>
    </body>
    </html>
    View Code

      2). 把请求提交到 SpringMVC 的 Handler
      3). Handler获取用户名和密码.

    2、获取当前的 Subject. 调用 SecurityUtils.getSubject();

    3、测试当前的用户是否已经被认证. 即是否已经登录. 调用 Subject 的 isAuthenticated() 

    4、若没有被认证, 则把用户名和密码封装为 UsernamePasswordToken 对象

    5、执行登录: 调用 Subject 的 login(AuthenticationToken) 方法.

    package com.nchu.shiro;
    
    import org.apache.shiro.SecurityUtils;
    import org.apache.shiro.authc.*;
    import org.apache.shiro.subject.Subject;
    import org.springframework.stereotype.Component;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestParam;
    
    /**
     * Created by yangshijing on 2018/1/16 0016.
     */
    @Component
    @RequestMapping("/shiro")
    public class ShiroController {
        public static  final String SUCCESS = "success";
        @RequestMapping("/login")
        public String login(@RequestParam("username") String username,@RequestParam("password") String password){
            //获取当前的 Subject
            Subject currentUser = SecurityUtils.getSubject();
            //判断当前的用户是否已经被认证
            if (!currentUser.isAuthenticated()) {
                //若没有被认证, 则把用户名和密码封装为 UsernamePasswordToken 对象
                UsernamePasswordToken token = new UsernamePasswordToken(username, password);
                token.setRememberMe(true);
                try {
                    //测试token是否和自定义中的Realm的入参token相同
                    System.out.println("++++++++>"+token.hashCode());
                    // 执行登录
                    currentUser.login(token);
    
                }
                catch (AuthenticationException ae) {
                    System.out.print("登录失败");
                    return "error";
                }
            }
            return "redirect:/shiro/list.jsp";
    
        }
    }
    View Code

    6、自定义 Realm 的方法, 从数据库中获取对应的记录, 返回给 Shiro.

    1). 需要继承 org.apache.shiro.realm.AuthenticatingRealm 类
    2). 实现 doGetAuthenticationInfo(AuthenticationToken token) 方法.

    7、由 shiro 完成对密码的比对.

    package com.nchu.shiro;
    
    import com.nchu.mvc.bean.PracticeUser;
    import com.nchu.mvc.dao.ShiroRealmMapper;
    import org.apache.shiro.authc.*;
    import org.apache.shiro.realm.AuthenticatingRealm;
    import org.springframework.beans.factory.annotation.Autowired;
    
    /**
     * Created by yangshijing on 2018/1/16 0016.
     */
    public class JdbcRealm extends AuthenticatingRealm {
        @Autowired
        ShiroRealmMapper shiroRealmMapper;
        @Override
        protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
            System.out.println("----->"+token.hashCode());
            //1. 把 AuthenticationToken 转换为 UsernamePasswordToken
            UsernamePasswordToken upToken = (UsernamePasswordToken) token;
    
            //2. 从 UsernamePasswordToken 中来获取 username
            String username = upToken.getUsername();
    
            //3. 调用数据库的方法, 从数据库中查询 username 对应的用户记录
    
            System.out.println("从数据库中获取 username: " + username + " 所对应的用户信息.");
            String password  = shiroRealmMapper.login(username);
            //4. 若用户不存在, 则可以抛出 UnknownAccountException 异常
            if(password==null){
                throw new UnknownAccountException("用户不存在!");
            }
    
            //5. 根据用户信息的情况, 决定是否需要抛出其他的 AuthenticationException 异常.
            /*  if("monster".equals(username)){
                throw new LockedAccountException("用户被锁定");
            }*/
            //6. 根据用户的情况, 来构建 AuthenticationInfo 对象并返回. 
            //通常使用的实现类为: SimpleAuthenticationInfo
            //以下信息是从数据库中获取的.
            //1). principal: 认证的实体信息. 可以是 username, 也可以是数据表对应的用户的实体类对象.
            Object principal = username;
            //2). credentials: 密码.
            Object credentials = password;
            //3). realmName: 当前 realm 对象的 name. 调用父类的 getName() 方法即可
            String realmName = getName();
            SimpleAuthenticationInfo info =
     new SimpleAuthenticationInfo(principal, credentials, realmName);
            return info;
        }
    }
               
    View Code

    mybatis框架从数据库中查询

    mapper接口

    package com.nchu.mvc.dao;
    import org.springframework.stereotype.Component;
    /**
     * Created by yangshijing on 2018/1/16 0016.
     */
    @Component
    public interface ShiroRealmMapper {
    
        String  login(String username);
    }
    mapper映射文件
    <?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="com.nchu.mvc.dao.ShiroRealmMapper">
        <select id="login" resultType="java.lang.String">
            SELECT password FROM practice_user
            Where user_name=#{userName}
        </select>
    
    </mapper>
  • 相关阅读:
    6
    5
    4
    3
    Hive常用的DCL(Data Control Language)数据操作
    Hive常用的DQL(Data Query Language)数据操作
    Hive常用的DML(Data Manipulation Language)数据操作
    Hive常用的DDL(Data Definition Language)数据操作
    Hive常用的数据类型概述
    Hive的JDBC环境部署
  • 原文地址:https://www.cnblogs.com/realshijing/p/8299245.html
Copyright © 2011-2022 走看看