总结内容

一、RBAC 的概念

RBAC 全称 Role Based Access Control,意思是基于角色的访问控制,说白了就是每个用户拥有不同的角色,每个角色又拥有不同的权限,用户通过所拥有的的权限对系统进行操作。
RBAC 是一种目前使用最普片的权限管理模型,该模型中有3个基础的组成部分,分别是:用户、角色、权限。我们接下来也是围绕这3个组成部分来进行的。

二、两种常用的权限管理框架

1. Apache Shiro

Apache Shiro是一个强大且易用的Java安全框架,执行身份验证、授权、密码和会话管理。使用Shiro的易于理解的API,我们可以快速、轻松地获得任何应用程序,从最小的移动应用程序到最大的网络和企业应用程序。

2. Spring Security

Spring Security是为基于Spring的应用程序提供声明式安全保护的安全性框架,它提供了完整的安全性解决方案,能够在web请求级别和方法调用级别处理身份证验证和授权。因为基于Spring框架,所以Spring Security充分利用了依赖注入和面向切面的技术。

3. Shiro 和 Spring Security 比较

Shiro 比 Spring Security更容易上手使用和理解,Shiro 可以不跟任何的框架或者容器绑定,可独立运行,而Spring Security 则必须要有Spring环境, Shiro 可能没有 Spring Security 做的功能强大,但是在实际工作时可能并不需要那么复杂的东西,所以使用小而简单的 Shiro 就足够了。对于它俩到底哪个好,这个不必纠结,能更简单的解决项目问题就好了。

三、Shiro 的概述

1. shiro 作用

1)认证
2)授权
3)加密
4)会话管理
5)与 Web 集成
6)缓存
7)…

2. shiro 架构

Shiro 主要组件包括:Subject,SecurityManager,Authenticator,Authorizer,SessionManager,CacheManager,Cryptography,Realms。

  1. Subject(用户)
    Subject即主体,外部应用与subject进行交互,subject记录了当前的操作用户,将用户的概念理解为当前操作的主体。Subject 可以是一个人,但也可以是第三方服务、守护进程帐户、时钟守护任务或者其它–当前和软件交互的任何事件。
    在程序任意位置可使用:Subject currentUser = SecurityUtils.getSubject() 获取到subject主体对象,类似 Employee user = UserContext.getUser() ;

  2. SecurityManager(安全管理器)
    它是 shiro 功能实现的核心,负责与后边介绍的其他组件(认证器/授权器/缓存控制器)进行交互,实现 subject 委托的各种功能。有点类似于SpringMVC 中的 DispatcherServlet 前端控制器,负责进行分发调度。

  3. Realms(数据源)
    Realm 充当了 Shiro 与应用安全数据间的“桥梁”或者“连接器”。;可以把Realm 看成 DataSource,即安全数据源。执行认证(登录)和授权(访问控制)时,Shiro 会从应用配置的 Realm 中查找相关的比对数据。以确认用户是否合法,操作是否合理。

  4. Authenticator(认证器)
    用于认证,从 Realm 数据源取得数据之后进行执行认证流程处理。

  5. Authorizer(授权器)
    用户访问控制授权,决定用户是否拥有执行指定操作的权限。

  6. SessionManager (会话管理器)
    Shiro 与生俱来就支持会话管理,这在安全类框架中都是独一无二的功能。即便不存在 web 容器环境,shiro 都可以使用自己的会话管理机制,提供相同的会话 API。

  7. CacheManager (缓存管理器)
    用于缓存认证授权信息等。

  8. Cryptography(加密组件)
    Shiro 提供了一个用于加密解密的工具包。

四、基于 ini 的认证案例实现

1. 实现原理图

2. 实现代码

2.1 添加 maven jar包依赖

<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.1.3</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-core</artifactId>
<version>1.5.2</version>
</dependency> <dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.22</version>
<scope>provided</scope>
</dependency>

2.2 编写 ini 配置文件:shiro-authc.ini

shiro默认支持的是ini配置的方式,这里只是为了方便,项目中还是会选择xml

#用户的身份、凭据
[users]
admin=123
xfy=123

2.3 使用 Shiro 相关的 API 完成身份认证

@Test
public void testLogin(){
//创建Shiro的安全管理器,是shiro的核心
DefaultSecurityManager securityManager = new DefaultSecurityManager();
//加载shiro.ini配置,得到配置中的用户信息(账号+密码)
IniRealm iniRealm = new IniRealm("classpath:shiro-authc.ini");
securityManager.setRealm(iniRealm);
//把安全管理器注入到当前的环境中
SecurityUtils.setSecurityManager(securityManager);
//无论有无登录都可以获取到subject主体对象,但是判断登录状态需要利用里面的属性来判断
Subject subject = SecurityUtils.getSubject();
System.out.println("认证状态:"+subject.isAuthenticated());
//创建令牌(携带登录用户的账号和密码)
UsernamePasswordToken token = new UsernamePasswordToken("dafei","666");
//执行登录操作(将用户的和 ini 配置中的账号密码做匹配)
subject.login(token);
System.out.println("认证状态:"+subject.isAuthenticated());
//登出
//subject.logout();
//System.out.println("认证状态:"+subject.isAuthenticated());
}

如果输入的身份和凭证和 ini 文件中配置的能够匹配,那么登录成功,登录状态为true,反之登录状态为false。

  • 登录失败一般存在两种情况
    【1】账号错误 org.apache.shiro.authc.UnknownAccountException
    【2】密码错误 org.apache.shiro.authc.IncorrectCredentialsException

五、项目中集成 Shiro 认证案例实现

1. 项目准备

1.1 添加依赖

<properties>
<shiro.version>1.5.2</shiro.version>
</properties>
<!--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>
<!--Freemarker 的 shiro 标签库-->
<dependency>
<groupId>net.mingsoft</groupId>
<artifactId>shiro-freemarker-tags</artifactId>
<version>1.0.1</version>
</dependency>

1.2 配置代理过滤器

在访问的时候,需要做一系列的预处理操作,Shiro是选择使用filter过滤器来进行拦截的,因为Shiro不依赖Spring容器,所以当没有springmvc时意味着不能用拦截器,但过滤器则不同,只要是web项目都可以使用。

  • web.xml 文件
<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>
</filter-mapping>

这里使用了一个代理过滤器DelegatingFilterProxy,因为真正的shiroFilter需要注入很多复杂的对象,而web.xml中只能配置字符串或数字的参数,是不能满足的,因此我们会把shiroFilter交给 Spring 进行管理,通过spring的xml文件来配置。 使用DelegatingFilterProxy代理过滤器后,但浏览器发送请求过来,被代理过滤器拦截到后,代理过滤器会自动从 spring 容器中找filter-name所配置相同名称的bean,来实现真正的业务。

2. 代码实现

2.1 登录的 LoginController 控制器

@RequestMapping("/userLogin")
@ResponseBody
public JsonResult login(String username, String password) {
try {
UsernamePasswordToken token = new UsernamePasswordToken(username, password); SecurityUtils.getSubject().login(token);
// JsonResult 是一个自定义的工具类,里面就 2 个参数,boolean 类型的 success,String 类型的 message
return new JsonResult();
} catch (UnknownAccountException e) {
return new JsonResult(false, "账号不存在");
} catch (IncorrectCredentialsException e) {
return new JsonResult(false, "密码错误");
} catch (Exception e) {
e.printStackTrace();
return new JsonResult(false, "登录异常,请联系管理员");
}
}

2.2 配置自定义Realm:CarBusinessRealm

/**
* 自定义Realm查询mysql
*/
public class CarBusinessRealm extends AuthorizingRealm {
@Autowired
private IEmployeeService employeeService;
//提供认证信息
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
//通过token获取用户名(用户登录的时候填的)
String username = (String)token.getPrincipal();
//判断是否存在数据库(根据名字查询员工)
Employee employee = employeeService.selectByUsername(username);
if(employee!=null){
//身份对象,真正的密码,当前realm的名字
return new SimpleAuthenticationInfo(employee, employee.getPassword(), this.getName());
}
//返回值就是查询出来的数据,如果查到这个账号,就应该返回该账号正确的数据,如果查不到,就返回null
return null;
}
//提供授权信息
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
return null;
}
}

2.3 创建 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"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd"> <!-- <aop:config/> 会扫描配置文件中的所有 advisor,并为其创建代理 -->
<!-- <aop:config/> --> <!-- Pointcut advisor 通知器,会匹配所有加了 shiro 权限注解的方法 -->
<!-- <bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">
<property name="securityManager" ref="securityManager"/>
</bean> --> <!-- 自定义 realm -->
<bean id="carBusinessRealm" class="cn.wolfcode.realm.CarBusinessRealm"/> <!-- 安全管理器 -->
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
<!-- 设置 realm 值-->
<property name="realm" ref="carBusinessRealm"/>
</bean> <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>
/userLogin=anon
/css/**=anon
/js/**=anon
/img/**=anon
/upload/**=anon
/static/**=anon
/userLogout=logout
/**=authc
</value>
</property>
</bean>
</beans>

2.4 在SpringMVC 中引入 shiro.xml

<import resource="classpath:shiro.xml"/>

2.5 安全管理器

在 JavaEE 环境中,我们需要使用的安全管理器是:DefaultWebSecurityManager

<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
<!-- 这里面有很多配置文件 -->
</bean>

有了上面的配置,当我们的访问到达具体资源之前,会先进过指定的过滤器做预处理,在允许通过之后才能继续访问。

  • Shiro 中定义了多个过滤器来完成不同的预处理操作
过滤器的名称 Java
anon org.apache.shiro.web. lter.authc.AnonymousFilter
authc org.apache.shiro.web. lter.authc.FormAuthenticationFilter
authcBasic org.apache.shiro.web. lter.authc.BasicHttpAuthenticationFilter
roles org.apache.shiro.web. lter.authz.RolesAuthorizationFilter
perms org.apache.shiro.web. lter.authz.PermissionsAuthorizationFilter
user org.apache.shiro.web. lter.authc.UserFilter
logout org.apache.shiro.web. lter.authc.LogoutFilter
port org.apache.shiro.web. lter.authz.PortFilter
rest org.apache.shiro.web. lter.authz.HttpMethodPermissionFilter
ssl org.apache.shiro.web. lter.authz.SslFilter

anon: 匿名处理过滤器,即不需要登录即可访问;一般用于静态资源过滤;

示例 /static/**=anon

authc: 表示需要认证(登录)才能使用;

示例 /**=authc

roles: 角色授权过滤器,验证用户是否拥有资源角色;

示例 /admin/*=roles[admin]

perms: 权限授权过滤器,验证用户是否拥有资源权限;

示例 /employee/input=perms[“user:update”]

logout: 注销过滤器

示例 /logout=logout

3. 注销功能

shiro.xml 中的路径规则加入 /logout=logout 即可交给shiro来处理,我们以前写的LoginController中的logout方法可以删掉啦。

总结

以上就是对Shiro 安全框架入门的总结了,代码仅供参考,欢迎讨论交流。
下篇博客:Shiro 安全框架详解二(概念+权限案例实现)

Shiro 安全框架详解一(概念+登录案例实现)的更多相关文章

  1. Shiro 安全框架详解二(概念+权限案例实现)

    Shiro 安全框架详解二 总结内容 一.登录认证 二.Shiro 授权 1. 概念 2. 授权流程图 三.基于 ini 的授权认证案例实现 1. 实现原理图 2. 实现代码 2.1 添加 maven ...

  2. (转) shiro权限框架详解06-shiro与web项目整合(上)

    http://blog.csdn.net/facekbook/article/details/54947730 shiro和web项目整合,实现类似真实项目的应用 本文中使用的项目架构是springM ...

  3. (转)shiro权限框架详解03-shiro介绍

    http://blog.csdn.net/facekbook/article/details/54893740 shiro介绍 本文正式进入主题.本文将介绍如下内容: 什么是shiro 为什么需要学习 ...

  4. shiro 安全框架 详解

    ---恢复内容开始--- Shiro 简介 简介• Apache Shiro 是 Java 的一个安全(权限)框架.• Shiro 可以非常容易的开发出足够好的应用,其不仅可以用在JavaSE 环境, ...

  5. (转)shiro权限框架详解06-shiro与web项目整合(下)

    http://blog.csdn.net/facekbook/article/details/54962975 shiro和web项目整合,实现类似真实项目的应用 web项目中认证 web项目中授权 ...

  6. (转)shiro权限框架详解05-shiro授权

    http://blog.csdn.net/facekbook/article/details/54910606 本文介绍 授权流程 授权方式 授权测试 自定义授权realm 授权流程 开始构造Secu ...

  7. (转) shiro权限框架详解04-shiro认证

    http://blog.csdn.net/facekbook/article/details/54906635 shiro认证 本文介绍shiro的认证功能 认证流程 入门程序(用户登录和退出) 自定 ...

  8. (转)shiro权限框架详解02-权限理论介绍

    http://blog.csdn.net/facekbook/article/details/54893042 权限管理解决方案 本文主要介绍权限管理的解决方法: 粗颗粒度和细颗粒度 基于url拦截 ...

  9. (转)shiro权限框架详解01-权限理论介绍

    http://blog.csdn.net/facekbook/article/details/54890365 权限管理 本文介绍权限管理的理论和权限管理的一些名词. 介绍权限管理 理解身份认证和授权 ...

随机推荐

  1. 小程序授权登录并 laravel7(laravel8) token 应用

    参考博客: https://blog.csdn.net/qq_42839386/article/details/118279530 1:composer 下载 composer require fir ...

  2. tp5(laravel7) ajax模型修改数据

    ① 设置ajax请求(10分) ② 后台更改数据值(10分) ③ 重新计算平均分(10分) ④ 无刷新更新评分结果(10分) 思路: 在详情页面中有一个评分的按钮,单击后进行修改数据,首先找见本条数据 ...

  3. CF1548B题解

    在日报上面看到的,发现 NOIP 模拟赛考过这个 trick( 首先我们把题目要求的条件这么写: \[a_i=x_i \times m+k \] 那么我们要找到满足条件的数组,差分后的数组一定都是 \ ...

  4. 什么是CSRF跨站请求伪造?(from表单效验csrf-ajdax效验csrf-Ajax设置csrf-CBV装饰器验证csrf)

    目录 一:csrf跨站请求伪造 1.什么是CSRF? 2.CSRF攻击案例(钓鱼网站) 3.钓鱼网站 内部原理 4.CSRF原理(钓鱼网站内部本质) 5.从上图可以看出,要完成一次CSRF攻击,受害者 ...

  5. 关于DP动规

    今天学了动规,简单记录一下自己理解了的:(要不俺就忘了) 首先,啥是DP??? 动态规划,其实就是组合子问题的解来解决整个问题的解,由于每个子问题他只判断一次,所以不会重复计算,那就很牛啊!!! 专业 ...

  6. DAViCal 跨站请求伪造漏洞

    受影响系统:DAViCal DAViCal <= 1.1.8描述:CVE(CAN) ID: CVE-2019-18346 DAViCal是一款日历共享服务器. DAViCal 1.1.8及之前版 ...

  7. Java基础——StringBuilder

    /* StringBuilder作用: String 在new一个新的对象以及进行字符串拼接时,会在常量池创建拼接之前的两个字符串对象,拼接完成后会造成内存浪费,时间浪费 StringBuilder ...

  8. 4月12日 python学习总结 继承和派生

    一.继承 什么是继承:   继承是一种新建类的方式,在python中支持一个子类继承多个父类   新建类称为子类或派生类   父类可以称之为基类或者超类   子类会遗传父类的属性 2.  为什么继承 ...

  9. 重写(Override)与重载(Overload)的区别(面试题)

    概念:重写(Override):是存在子父之间的关系,子类里定义的方法与父类里定义的方法具有相同的方法名以及相同的返回值和参数类型 重写规则: 1.方法名形参列表相同: 2.访问权限,子类大于等于父类 ...

  10. 从零开始,开发一个 Web Office 套件(13):删除、替换已选中文字

    这是一个系列博客,最终目的是要做一个基于 HTML Canvas 的.类似于微软 Office 的 Web Office 套件(包括:文档.表格.幻灯片--等等). 博客园:<从零开始, 开发一 ...