THIS IS B3c0me

记录生活中的点点滴滴

0%

基于Shiro框架实现的登录认证系统

前言

参考文章:

  1. https://blog.csdn.net/u012581020/article/details/130627795

一、Shiro框架概述

Shiro 的基本组件包括 Subject、SecurityManager 和 Realms 等。下面我们分别介绍一下这些组件的作用。

Subject
Subject 代表当前用户,是 Shiro 框架中最重要的组件之一。Subject 封装了用户的所有信息,包括身份(用户名和密码)和角色等。在一个应用程序中,可能有多个 Subject,每个 Subject 可以访问应用程序中的资源。

用户可以通过 Subject 登录应用程序,并执行诸如访问资源、修改个人配置等操作。Shiro 提供了简单易用的方法来管理用户的登录和退出行为,以及 Session 管理等。

SecurityManager
SecurityManager 是 Shiro 的核心组件,负责管理和协调整个应用程序的安全机制。它的主要职责是认证、授权、加密和会话管理等。

SecurityManager 将应用程序中的所有安全操作委托给适当的 Realms 进行处理,并存储和管理有关用户身份、角色和权限等信息。SecurityManager 还可以配置多个 Realms,以便应用程序可以集成不同的认证和授权方案。

Realm
Realm 是 SecurityManager 中负责处理用户身份认证和授权的组件。Shiro 支持多种不同类型的 Realm,包括 JDBC Realm、LDAP Realm、Active Directory Realm 等。

每个 Realm 负责验证用户的身份,并获取用户的权限信息,以便 SecurityManager 可以根据这些信息进行访问控制和授权。Realm 还可以实现缓存机制,提高系统性能。

二、RBAC模型

Role Based Access Control 基于角色的访问控制

模型中的三个主体:用户 角色 权限

每个角色可以有多个权限,每个权限可以分配给多个角色

每个用户可以有多个角色,每个角色可以分配给多个用户

——>两个多对多

  • 权限访问控制,需要做的事是:
    • 身份校验:判断是否为合法用户
    • 权限校验:用户要做某件事或使用某些资源,必须拥有某角色,或必须用有某权限
  • 访问控制管理的过程:
    • 记录用户信息
    • 制定角色
    • 对资源制定权限
    • 将权限分配给不同的角色
    • 将角色分配给具体的用户

三、Shiro入门程序

3.1 pom文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-core</artifactId>
<version>1.7.1</version>
</dependency>

<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>2.0.5</version>
</dependency>

<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>2.0.5</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.12</version>
</dependency>
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.2</version>
</dependency>

3.2 配置

创建一个shiro.ini文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#定义用户信息
#格式:用户名=密码,角色1,角色2...
[users]
zhangsan=123,admin
lisi=456,manager,seller
wangwu=789,clerk
#----------------------------------------------------------
#角色及其权限信息
#预定权限:user:query
# user:detial:query
# user:update
# user:delete
# user:insert
# order:update
# ...

[roles]
#admin 拥有所有权限,用*表示
admin=*
#clerk只有查询权限
clear=user:query,user:detial:query
# manager有user的所有权限
manager=user:*

3.3 代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
public class TestShiro {
public static void main(String[] args) {
//创建SecurityFactory,加载ini配置并通过它创建SecurityManager
IniSecurityManagerFactory factory = new IniSecurityManagerFactory("classpath:shiro.ini");
//shiro核心:securityManager
SecurityManager securityManager = factory.getInstance();

//将SecurityManger托管到SecurityUtils工具类中
SecurityUtils.setSecurityManager(securityManager);
//获取Subject,直接由用户使用,其底层调用SecurityManager的相关流程。通过Subject对象可以执行shiro相关的操作,如身份认证和授权等
Subject subject = SecurityUtils.getSubject();


//通过subject 进行身份认证(类似登录逻辑)
if (!subject.isAuthenticated()) {
//未登录,封装一个token,其中包含用户名和密码
UsernamePasswordToken zhangsan = new UsernamePasswordToken("zhangsans", "123");
try {
//将token传入login方法,进行身份验证
subject.login(zhangsan); //登录失败会抛出异常
System.out.println("登录成功");
} catch (UnknownAccountException e) {//用户不存在
System.out.println("There is no user with username of " + zhangsan.getPrincipal());
} catch (IncorrectCredentialsException e) {//密码错误
System.out.println("Password for account " + zhangsan.getPrincipal() + "was incorrect!");
} catch (LockedAccountException e) {//账户冻结
System.out.println("The account is locked");
} catch (AuthenticationException e) {//其他认证异常
//...
}
}

//进行角色校验
if(subject.hasRole("admin")){//校验角色
System.out.println("hello,boss");
} else {
System.out.println("hello,user");
}

//进行权限校验
if(subject.isPermitted("user:update")){
System.out.println("you can update");
} else {
System.out.println("sorry,you are not allowed to update");
}

//退出登录
subject.logout();
}
}

3.4 权限规则

最常用的权限标识:【资源 :操作

image-20231127231852409

四、web项目集成

与web项目集成后,shiro的工作模式如下:

如上图所示:

  • ShiroFilter会拦截浏览器的所有请求,对于请求做访问控制(即判断是否满足身份,角色,权限)
  • 如果没有做身份认证,则强制跳转到登录页面
  • 如果没有充分的角色或权限,则跳转到权限不足的页面
  • 如果校验成功,则顺利执行业务逻辑

4.1 POM

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
<dependencies>
<dependency>
<groupId>jakarta.servlet</groupId>
<artifactId>jakarta.servlet-api</artifactId>
<version>5.0.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.1.1</version>
</dependency>


<!--shiro依赖-->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-core</artifactId>
<version>1.10.0</version>
</dependency>

<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>2.0.5</version>
</dependency>

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


<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>2.0.5</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.12</version>
</dependency>

<!--Servlet-->
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>

<!--SpringMVC-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>4.3.6.RELEASE</version>
</dependency>

</dependencies>

4.2 代码:Servlet

4.3 配置

4.3.1 web.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<!--
1.在项目的最外层构建访问控制层
2.在启动时,初始化Shiro环境
-->
<filter>
<filter-name>shiroFilter</filter-name>
<filter-class>org.apache.shiro.web.servlet.ShiroFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>shiroFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!--
在项目启动时,加载web-info 或 classpath下的shiro.ini,并构建WebSecurityManager
构建所有配置中使用过的过滤器链,ShiroFilter会获取此链
-->
<listener>
<listener-class>org.apache.shiro.web.env.EnvironmentLoaderListener</listener-class>
</listener>

4.3. shiro.ini

1

4.3.3 其他默认过滤器

欢迎关注我的其它发布渠道