shiro框架
什么是shiro
shiro是apache旗下一个Java安全框架,它将软件系统的安全认证相关的功能抽取出来,实现用户身份认证、权限授权、加密、会话管理等功能,组成了一个通用的安全认证框架。使用shiro就可以非常快速的完成认证、授权、加密,会话管理等功能的开发,可为任何应用提供安全保障,降低系统成本
基础RBAC
Shiro功能
- 登录/身份认证,登录失败次数限制
- 对用户执行访问控制,如: 判断用户是否拥有角色admin,判断用户是否拥有访问的权限
- 在任何环境下使用Session API。例如CS程序
- 加密,保证数据安全;
- 可以使用多个用户数据源。例如一个是oracle用户库,另外一个是mysql用户库
- Caching缓存(支持分布式cache管理);
- 单点登录SSO功能
- "Remember Me"服务,类似购物车的功能,shiro官方建议开启
- Run As允许一个用户假装为另一个用户(如果他们允许)的身份进行访问;
- Shiro可以很友好的与Spring集成,支持jsp标签
Shiro三大核心组件
Shiro有三大核心的组件:Subject、SecurityManager 和 Realm
ApplicationCode为客户端,在Web环境中为登录的Controller,使用者只需要创建一个Subject对象,调用其上的login()方法,即可完成登录。在使用者角度只需要在SpringIOC容器中配置ShiroSecurityManager注入Realm即可简单使用
Subject认证主体,是需要认证的东西,最常见的就是用户名密码。它包含两个信息Principals和Credentials
- Principals身份。可以是用户名,邮件,手机号码等,用来标识一个登录主体身份
- Credentials凭证。常见有密码,数字证书等等。
SecurityManager安全管理员。这是Shiro架构的核心,它就像Shiro内部所有原件的保护伞一样。在项目中一般都会配置SecurityManager,开发人员大部分精力主要是在Subject认证主体上面。在与Subject进行交互的时候,实际上是SecurityManager在背后做一些安全操作
Realm是一个域,它是连接Shiro和具体应用的桥梁,当需要与安全数据交互的时候,比如用户账户、访问控制等,Shiro就会从一个或多个Realm中去查找。可以把Realm看成DataSource,即安全数据源,一般会自己定制Realm,在自定义Realm中一般会从数据库中获取和认证相关的信息
Shiro编码实现
基础使用
不引入spring框架
依赖
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-all</artifactId>
<version>1.7.1</version>
</dependency>
shiro1.ini用于存放用户信息
[users] # 对用户信息进行配置
yanjun=123456
zhangsan=333333
编程测试
public class ShiroTest {
@Test
public void testLogin() throws Exception {
// 创建SecurityManager
DefaultSecurityManager securityManager = new DefaultSecurityManager();
//通过ini配置文件创建securityManager工厂
IniRealm iniRealm=new IniRealm("classpath:shiro1.ini");
securityManager.setRealm(iniRealm);
// 将securityManager设置当前的运行环境中
SecurityUtils.setSecurityManager(securityManager);
// 从SecurityUtils里边创建一个subject
Subject subject = SecurityUtils.getSubject();
// 在认证提交前准备token令牌,账号和密码是由用户输入进去
UsernamePasswordToken token = new UsernamePasswordToken("yanjun", "123456");
try {
// 执行认证提交
subject.login(token);
} catch (AuthenticationException e) {
e.printStackTrace();
}
// 是否认证通过
boolean isAuthenticated = subject.isAuthenticated();
System.out.println("是否认证通过:" + isAuthenticated);
// 退出操作
subject.logout();
// 是否认证通过
isAuthenticated = subject.isAuthenticated();
System.out.println("是否认证通过:" + isAuthenticated);
}
}
Realms充当Shiro与应用程序安全数据之间的桥梁,简而言之Shiro是从Realms中获取安全数据,其中包括用户、角色、权限等信息。Shiro提供了一些常用的Realm,例如IniRealm、JdbcRealm)等,Shiro默认使用的Realm,它是从ini文件中获取用户、角色、权限。
ini文件它可以配置用户,角色,权限以及Realm等SecurityManager管理的组件
[users]部分允许定义一组静态用户帐户。这在用户帐户数量很少或不需要在运行时动态创建用户帐户的环境中非常有用。[users]配置格式为username = password,roleName1,roleName2…
- 等号左侧的值为用户账户
- 右侧第一个值为用户密码
- 右侧其他的值为用户的角色,一个用户可以配置多个角色
Step1:应用程序代码在调用Subject.login(token) 方法后,传入代表最终用户的身份和凭证的 AuthenticationToken实例 token。
Step2:将 Subject 实例委托给应用程序的 SecurityManager(Shiro的安全管理)来开始实际的认证工作。这里开始真正的认证工作了。
Step3,4,5:然后 SecurityManager 就会根据具体的 realm 去进行安全认证了。realm可以使用系统预定义的,也可以自定义(Custom Realm)
使用自定义realm实现认证
库表结构可以参照RBAC模型
用户—角色—权限(资源),相互关系为n:m
用户认证实现
依赖
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring-boot-web-starter</artifactId>
<version>1.7.1</version>
</dependency>
持久层
<!-- https://mvnrepository.com/artifact/tk.mybatis/mapper-spring-boot-starter -->
<dependency>
<groupId>tk.mybatis</groupId>
<artifactId>mapper-spring-boot-starter</artifactId>
<version>2.1.5</version>
</dependency>
定义表结构
create table if not exists t_users(
id bigint primary key auto_increment,
username varchar(20) not null unique,
password varchar(20) not null
)engine=innodb default charset utf8;
定义实体类
@Data
@Table(name="t_users")
public class User implements Serializable {
@Id
@GeneratedValue(strategy= GenerationType.IDENTITY)
@KeySql(useGeneratedKeys = true)
private Long id;
@Column(name="username",length = 20,nullable = false,unique = true)
private String username;
private String password;
}
定义mapper接口
@Repository
public interface UserMapper extends Mapper<User> {
}
在主类上添加注解,实现Mapper接口的自动注册
@MapperScan("com.yan.com.yan.dao")
@SpringBootApplication
public class Shiro1Application {
public static void main(String[] args) {
SpringApplication.run(Shiro1Application.class, args);
}
}
定义核心配置application.yml
# 配置数据源
spring:
datasource:
druid:
driver-class-name: com.mysql.cj