SSM 整合 Shiro 安全框架

1、介绍

(1)Shiro 是什么?

  • Shiro 是一个功能强大和易于使用的 Java安全框架
  • Shiro 为开发人员提供一个直观而全面的解决方案:认证、授权、加密、会话管理、Web集成、缓存等。
  • Apache ShiroSpring Security 是同类型的框架,主要用来做安全方面,也就是我们俗称的权限校验(控制)Shiro 扩展更简单和灵活。

(2)Shiro 四个主要的功能

在这里插入图片描述

  • Authentication:身份认证/登录,验证用户是不是拥有相应的身份
  • Authorization:授权,即权限验证,判断某个已经认证过的用户是否拥有某些权限访问某些资源,一般授权会有角色授权和权限授权
  • SessionManager:会话管理,即用户登录后就是一次会话,在没有退出之前,它的所有信息都在会话中;会话可以是普通JavaSE环境的,也可以是如Web环境的,web 环境中作用是和 HttpSession 是一样的;
  • Cryptography:加密,保护数据的安全性,如密码加密存储到数据库,而不是明文存储;

(3)Shiro 其他的几个特点

  • Web Suppor:Web支持,可以非常容易的集成到Web环境;
  • Caching:缓存,比如用户登录后,其用户信息、拥有的角色/权限不必每次去查,这样可以提高效率;
  • Concurrency:shiro支持多线程应用的并发验证,即如在一个线程中开启另一个线程,能把权限自动传播过去;
  • Testing:提供测试支持;
  • Run As:允许一个用户假装为另一个用户(如果他们允许)的身份进行访问;
  • Remember Me:记住我,这个是非常常见的功能,即一次登录后,下次再来的话不用登录了。

(4)Shiro 架构

在这里插入图片描述

从图中我们可以看到不管是任何请求都会经过 SecurityManager 拦截并进行相应的处理,shiro 几乎所有的功能都是由 SecurityManager 来管理。

其中:

  • Subject:主体,相当与是请求过来的"用户"

  • SecurityManager: 是 Shiro 的心脏;所有具体的交互都通过 SecurityManager 进行拦截并控制;它管理着所有 Subject、且负责进行认证和授权、及会话、缓存的管理

  • Authenticator:认证器,负责主体认证的,即确定用户是否登录成功,我们可以使用  Shiro 提供的方法来认证,有可以自定义去实现,自己判断什么时候算是用户登录成功

  • Authrizer:授权器,即权限授权,给 Subject 分配权限,以此很好的控制用户可访问的资源

  • Realm:一般我们都需要去实现自己的 Realm ,可以有1个或多个 Realm,即当我们进行登录认证时所获取的安全数据来源(帐号/密码)

  • SessionManager:为了可以在不同的环境下使用 session 功能,shiro 实现了自己的 sessionManager ,可以用在非 web 环境下和分布式环境下使用

  • SessionDAO:对 session 的 CURD 操作

  • CacheManager:缓存控制器,来管理如用户、角色、权限等的缓存的

  • Cryptography:密码模块,Shiro提高了一些常见的加密组件用于如密码加密/解密的。


(4)官方文档中文版

Shiro 官方文档




2、开始整合

(1)导入 Maven 依赖

<!-- Shiro 安全框架 -->
<dependency>
	<groupId>org.apache.shiro</groupId>
	<artifactId>shiro-core</artifactId>
	<version>1.2.1</version>
</dependency>

<dependency>
	<groupId>org.apache.shiro</groupId>
	<artifactId>shiro-web</artifactId>
	<version>1.2.1</version>
</dependency>

<dependency>
	<groupId>org.apache.shiro</groupId>
	<artifactId>shiro-ehcache</artifactId>
	<version>1.2.1</version>
</dependency>

<!--与 Spring 进行整合的依赖-->
<dependency>
	<groupId>org.apache.shiro</groupId>
	<artifactId>shiro-spring</artifactId>
	<version>1.2.1</version>
</dependency>

(2)编写自定义 Realm 类

package com.yanghui.shiro;

import com.yanghui.pojo.User;
import com.yanghui.service.UserService;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.beans.factory.annotation.Autowired;

public class UserRealm extends AuthorizingRealm {
    @Autowired
    private UserService userService;

    /**
     * 认证
     * @param token
     * @return
     * @throws AuthenticationException
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        /** 获取用户名称 */
        String username = (String) token.getPrincipal();
        User user = userService.selectUserByUsername(username);

        /** 如果用户不存在 */
        if (user == null) {
            System.out.println("认证:当前登录的用户不存在!");
            throw new UnknownAccountException("认证:当前登录的用户不存在!");
        }

        /**
         * user:是从数据库中查出来的用户,也可以写 user.getUsername()
         *      SecurityUtils.getSubject().getPrincipal() 得到的就是这个参数
         * user.getPassword():是从数据库中查出来的密码,Shiro 会自动和用户输入的密码进行比对
         * getName():当前 realm 的名字
         */
        return new SimpleAuthenticationInfo(user, user.getPassword(), getName());
    }

    /**
     * 授权
     * @param principals
     * @return
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        return null;
    }
}


(3)编写 Shiro 配置文件

我的Shiro 配置文件名称为:spring-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.xsd">

    <!-- 配置 Shiro 安全管理器 -->
    <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
        <property name="realms" ref="userRealm"/>
    </bean>

    <!-- 自定义 Realm,这里 class 属性写上面自定义 Realm 类的路径 -->
    <bean id="userRealm" class="com.yanghui.shiro.UserRealm">
        <!-- 这个属性的意思是使用加密算法匹配用户密码,也可以不设置这个属性 -->
        <property name="credentialsMatcher" ref="credentialsMatcher"/>
    </bean>

    <!-- Shiro 工厂 Bean 配置 -->
    <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
        <!-- Shiro 的核心安全接口 -->
        <property name="securityManager" ref="securityManager"/>
        <!-- 请求需要权限的页面,要求登录时的连接 -->
        <property name="loginUrl" value="/admin/login"/>
        <!-- 登录成功时要跳转的连接 -->
        <property name="successUrl" value="/index.jsp"/>
        <!-- 未认证时要跳转的连接 -->
        <property name="unauthorizedUrl" value="/admin/login.jsp"/>
        <!-- Shiro 连接约束配置-->
        <property name="filterChainDefinitions">
            <value>
                <!-- 对静态资源设置匿名访问 -->
                /static/** = anon
                <!-- 可匿名访问路径,例如验证码、登录连接、退出连接等 -->
                <!-- 验证码 -->
                /admin/captcha = anon
                /admin/refreshCaptcha = anon
                <!-- 登录页面 -->
                / = anon
                /index.jsp = anon
                /page/** = anon
                /admin/login.jsp = anon
                <!--配置检查登录控制器地址可以匿名访问,不然无法登录-->
                /admin/checkLogin = anon
                /* = anon
                /find/* = anon
                /result/* = anon
                <!-- 剩余其他路径,必须认证通过才能访问 -->
                /** = authc
            </value>
        </property>
    </bean>

    <!-- 配置凭证算法匹配器 -->
    <bean id="credentialsMatcher" class="org.apache.shiro.authc.credential.HashedCredentialsMatcher">
        <!-- MD5 算法 -->
        <property name="hashAlgorithmName" value="MD5"/>
    </bean>
</beans>

(4)在 web.xml 中配置 Shiro 过滤器

代码如下:

<!-- Spring 整合 Shiro 框架-->
<!--配置 Shiro 拦截器 -->
<filter>
    <filter-name>shiroFilter</filter-name>
    <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
    <!--初始化参数-->
    <init-param>
        <!--这里写Shiro 配置文件中 Shiro 工厂 Bean 配置 的 id-->
        <!--也可以不配置此参数,默认会去寻找 id为shiroFilter 的 bean -->
        <param-name>targetBeanName</param-name>
        <param-value>shiroFilter</param-value>
    </init-param>
    
    <init-param>
       <param-name>targetFilterLifecycle</param-name>
       <param-value>true</param-value>
    </init-param>
</filter>

(5)开始测试

    /**
     * 验证用户名和密码
     */
    @RequestMapping("/checkLogin")
    public String login(
            String username,
            String password,
            Model model) {
        String result = "";

        UsernamePasswordToken token = new UsernamePasswordToken(username, password);
        Subject currentUser = SecurityUtils.getSubject();

        try {
            if (!currentUser.isAuthenticated()) {
                /** 记住密码 */
                token.setRememberMe(true);
                /** 验证角色和权限 */
                currentUser.login(token);
            }
            model.addAttribute("status", 200);
            /** 验证成功,跳转到后台首页 */
            result = "admin/index2";
            /** 将用户名保存到 Session 域中 */
            session.setAttribute("username", username);
        } catch (Exception e) {
            /** 验证失败,跳转到登录页面 */
            result = "admin/login";
            model.addAttribute("status", 500);
            model.addAttribute("message", "用户名或密码错误");
        }

        return result;
    }

(6)注意

当某用户登录成功之后,shiro安全框架就会将用户的信息存放在session中,你可以通过User user = (User) SecurityUtils.getSubject().getPrincipal()。这句代码在任何地方任何时候都能获取当前登录成功的用户信息。




3、整合完成!!!

完结撒花!!!

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值