美文网首页
CRM项目03-shiro01

CRM项目03-shiro01

作者: 建国同学 | 来源:发表于2020-05-20 10:52 被阅读0次

    一、权限管理

      1. Apache Shiro
        Apache Shiro 是一个强大且易用的 Java 安全框架,执行身份验证、授权、密码和会话管理。使
        用 Shiro 的易于理解的 API,您可以快速、轻松地获得任何应用程序,从最小的移动应用程序到最
        大的网络和企业应用程序。
      1. Spring Security
        Spring Security 以前叫做 acegi,是后来才成为 Spring 的一个子项目,也是目前最为流行的一个
        安全权限管理框架,它与 Spring 紧密结合在一起。
    • 使用:shiro轻量级,易使用,独立运行,security 对 spring 结合较好,如果项目用的 springmvc ,使用起来很方便

    二、 shiro

    Shiro 是 Java 的一个安全框,Shiro 可以帮助我们完成:认证、授权、加密、会话管理、与 Web 集成、缓存等架

    1. Subject(用户): 访问系统的用户,主体可以是用户、程序等,进行认证的都称为主体;
      Subject 一词是一个专业术语,其基本意思是“当前的操作用户”。它是一个抽象的概念,可以是
      人,也可以是第三方进程或其他类似事物,如爬虫,机器人等。 在程序任意位置:Subject
      currentUser = SecurityUtils.getSubject(); 类似 Employee user = UserContext.getUser()
      一旦获得 Subject,你就可以立即获得你希望用 Shiro 为当前用户做的 90%的事情,如登录、
      登出、访问会话、执行授权检查等
    2. SecurityManager(安全管理器) 安全管理器,它是 shiro 功能实现的核心,负责与后边介绍的
      其他组件(认证器/授权器/缓存控制器)进行交互,实现 subject 委托的各种功能。有点类似于
      SpringMVC 中的 DispatcherServlet 前端控制器。
    3. Realms(数据源) Realm 充当了 Shiro 与应用安全数据间的“桥梁”或者“连接器”。;可以把
      Realm 看成 DataSource,即安全数据源。执行认证(登录)和授权(访问控制)时,Shiro 会
      从应用配置的 Realm 中查找相关的比对数据。以确认用户是否合法,操作是否合理
    4. Authenticator Authenticator 用于认证,协调一个或者多个 Realm,从 Realm 指定的数据源取得
      数据之后进行执行具体的认证。
    5. Authorizer Authorizer 用户访问控制授权,决定用户是否拥有执行指定操作的权限。
    6. SessionManager Shiro 与生俱来就支持会话管理,这在安全类框架中都是独一无二的功能。即
      便不存在 web 容器环境,shiro 都可以使用自己的会话管理机制,提供相同的会话 API。
    7. CacheManager 缓存组件,用于缓存认证信息等。
    8. Cryptography Shiro 提供了一个加解密的命令行工具 jar 包,需要单独下载使用。

    Shiro 架构的核心(Subject,SecurityManager,Realms)

    三、shiro的使用

    subject 主体 ,当前登录用户 (里面有个状态可以区分是否有登录)
    securityManager 安全管理器,管理很多组件,分发调度
    realm数据源 , 提供数据给shiro进行逻辑处理

    • 常见认证登录失败存在错误:
    1. 账号错误
      org.apache.shiro.authc.UnknownAccountException
    2. 密码错误
      org.apache.shiro.authc.IncorrectCredentialsException

    四、CRM 中集成 Shiro 认证

    添加依赖

    <shiro.version>1.5.2</shiro.version>
    <!--shiro 核心 -->
    <dependency>
      <groupId>org.apache.shiro</groupId>
      <artifactId>shiro-core</artifactId>
      <version>${shiro.version}</version>
    </dependency>
    <!--shiro 的 Web 模块 -->
    <dependency>
      <groupId>org.apache.shiro</groupId>
      <artifactId>shiro-web</artifactId>
      <version>${shiro.version}</version>
    </dependency>
    <!--shiro 和 Spring 集成 -->
    <dependency>
      <groupId>org.apache.shiro</groupId>
      <artifactId>shiro-spring</artifactId>
      <version>${shiro.version}</version>
    </dependency>
    <!--shiro 底层使用的 ehcache 缓存 -->
    <dependency>
      <groupId>org.apache.shiro</groupId>
      <artifactId>shiro-ehcache</artifactId>
      <version>${shiro.version}</version>
    </dependency>
    <!--shiro 依赖的日志包 -->
    <dependency>
      <groupId>commons-logging</groupId>
      <artifactId>commons-logging</artifactId>
      <version>1.2</version>
    </dependency>
    <!--shiro 依赖的工具包 -->
    <dependency>
      <groupId>commons-collections</groupId>
      <artifactId>commons-collections</artifactId>
      <version>3.2.1</version>
    </dependency>
    <!--Freemarker 的 shiro 标签库 -->
    <dependency>
      <groupId>net.mingsoft</groupId>
      <artifactId>shiro-freemarker-tags</artifactId>
      <version>1.0.1</version>
      <exclusions>
        <exclusion>
          <groupId>org.apache.shiro</groupId>
          <artifactId>shiro-all</artifactId>
        </exclusion>
      </exclusions>
    </dependency>
    

    配置shiro代理过滤器

    shiro 过虑器,DelegatingFilterProx 会从 spring 容器中找 shiroFilter
    web.xml

    <!-- spring 提供的代理过滤器,当代理过滤器接收到请求后,会在spring容器中找真正的bean<filter-name>来执行 -->
        <filter>
            <filter-name>shiroFilter</filter-name>
            <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
        </filter>
        <filter-mapping>
            <filter-name>shiroFilter</filter-name>
            <servlet-name>springDispatcherServlet</servlet-name>
            <!-- 使用/*可以拦截所有资源,包括静态资源,可以更好的对静态资源进行权限判断 -->
            <url-pattern>/*</url-pattern>
        </filter-mapping>
    

    配置数据源(realm)

    CrmRealm.java

    @Component
    public class CrmRealm extends AuthorizingRealm {
    
        @Autowired
        private EmployeeMapper employeeMapper;
    
        @Override
        @Autowired
        // 注入凭证匹配器
        public void setCredentialsMatcher(CredentialsMatcher credentialsMatcher) {
            super.setCredentialsMatcher(credentialsMatcher);
        }
    
        @Override
        protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
            // 通过tokan获取用户名(用户登录的时候填的)
            Object username = token.getPrincipal();
            // 判断是否存在数据库
            Employee employee = employeeMapper.selectByName((String) username);
            // 判断是否账号被禁用
            if (!employee.isStatus()){
                throw new DisabledAccountException();
            }
            if (employee!=null) {
                // 一个项目可以有多个realm, 查出来的数据从哪个realm中查出来的 ,需要标记一下
                // 身份信息,凭证信息(正确),盐,当前realm的名字
                return new SimpleAuthenticationInfo(employee,employee.getPassword(),
                        ByteSource.Util.bytes(username),"CrmRealm");
            }
            // 返回值就是查询出来的数据,如果查到这个账号,就应该返回该账号的正确的数据,如果查询不到返回null
            return null;
        }
         /**
         * 授权,代码中需要 判断授权 hasxxx的时候才会执行
         *
         * @param principalCollection
         * @return
         */
        @Override
        protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
            return null;
        }
    }
    

    配置真正的shiro过滤器(在 mvc.xml 中引入)

    shiro.xml

    <!-- shiro过滤器 spring管理 -->
        <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
            <!--引用指定的安全管理器-->
            <property name="securityManager" ref="securityManager"/>
            <!-- shiro默认的登录地址是login.jsp,现在指定为自己的登录页面地址 -->
            <property name="loginUrl" value="/login.html"/>
            <!-- 路径对应的规则 -->
            <property name="filterChainDefinitions">
                <!-- 有前后顺序,先配置先生效 -->
                <value>
                    /login.do=anon
                    /css/**=anon
                    /js/**=anon
                    /logout.do=logout
                    /**=authc
                </value>
            </property>
        </bean>
    
        <!-- 安全管理器 分发调度-->
        <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
            <!-- 配置数据源 -->
            <property name="realm" ref="crmRealm"/>
            <!-- 注册缓存管理器 -->
            <property name="cacheManager" ref="cacheManager"/>
        </bean>
    

    登录功能

    //封装令牌
    UsernamePasswordToken token = new UsernamePasswordToken(username, password);
    // 利用shiro的api来进行登录
    SecurityUtils.getSubject().login(token);
    

    注销功能

    shiro.xml直接配置 /logout.do = logout 交给shiro提供的注销过滤器去处理

    密码加密

    密码加密加盐.png
    • 指定加密使用的盐为当前用户的用户名
    // 身份信息,凭证信息(正确),盐,当前realm的名字
    return new SimpleAuthenticationInfo(employee,employee.getPassword(), ByteSource.Util.bytes(username),"CrmRealm");
    
    • 在添加员工时,先加密,再保存
      (密码+用户名)的加盐方式
            // 密码进行加密(盐)
            Md5Hash md5HashPwd = new Md5Hash(employee.getPassword(), employee.getName());
            employee.setPassword(md5HashPwd.toString());
    
    • shiro.xml配置凭证匹配器,配置算法,注入realm,在realm中传入盐的数据

    shiro.xml

    <!-- 凭证匹配器 -->
        <bean id="credentialsMatcher" class="org.apache.shiro.authc.credential.HashedCredentialsMatcher">
            <!-- 加密的算法 -->
            <property name="hashAlgorithmName" value="md5"/>
            <!--<property name="hashIterations" value="50"/>-->
        </bean>
    

    相关文章

      网友评论

          本文标题:CRM项目03-shiro01

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