Sorry, your browser cannot access this site
This page requires browser support (enable) JavaScript
Learn more >

shiro安全框架

1、简述

shiro是apache公司所出品的开源安全框架
其可以用于:

  1. 处理身份认证
  2. 授权
  3. 企业会话管理和加密

相对于Spring security来说更加简单,使用也更加灵活

在使用shiro的时候可以不依赖于任何容器,既可以在javaSE下使用,同样可以在JavaEE下使用

2、架构

  1. 使用用户的登录信息构建令牌
    1
    2
    UsernamePasswordToken token = new UsernamePasswordToken(username, password);

    token可以理解为一个用户令牌,等于的过程可以理解为shiro检验用户令牌是否具有合法的身份以及相关的权限
  2. 执行登录
1
2
3
SecurityUtils.setSecurityManager(securityManager); // 注入SecurityManager
Subject subject = SecurityUtils.getSubject(); // 获取Subject单例对象
subject.login(token); // 执行登录

shiro中最核心的部分就是securityManger,它主要负责安全认证和授权。当我们在使用这个框架的时候,shiro已经将一切的操作封装成一个盒子了,我们在使用的时候可以把它当成一个黑盒来进行使用。SecurityUtils对象,本质上就是一个工厂类似Spring中的ApplicationContext。Subject,翻译过来就是项目的意思,他是一个需要通过shiro保护的一个抽象概念。
通过1令牌和项目的登录关系,保证了我们的安全。

  1. 判断用户

这一步中的内容shiro无法帮我们进行实现,我们只有通过最原始的手段来实现登录用户的判断,就是查询数据库。

例如:

1
2
3
4
5
6
if (!token.getUsername().equals(name)) {
//shiro底层会抛出一个异常
return null;
}
//判断密码
return new SimpleAuthenticationInfo("", password, "");

第一个if语句中首先会判断数据库中查到的name于输入的用户名2是否一致,如果不一致,则会抛出一个异常
然后SimpleAuthenticationInfo中可以用于判断密码的正确性,同样是从数据库查出来的数据做对比。

3、实现Realm

  1. 创建一个Realm

Realm即领域,相当于datasource数据源,securityManager进行安全认证需要通过Realm获取用户权限数据,比如:如果用户身份数据在数据库那么realm就需要从数据库获取用户身份信息,但是Realm并不止局限于数据的存取,其中还有很多认证授权校验相关的代码
我们可以自定义一个MyRealm,用于我们的项目之中,但是前提是这个类必须继承于AuthorizingRealm父类,然后实现两个方法
AuthorizationInfo doGetAuthorizationInfo以及AuthenticationInfo doGetAuthenticationInfo
AuthenticationInfo代表了用户的角色信息集合,AuthorizationInfo代表了角色的权限信息集合。如此一来,当设计人员对项目中的某一个url路径设置了只允许某个角色或具有某种权限才可以访问的控制约束的时候,Shiro就可以通过以上两个对象来判断。

我们也可以简单看作:
doGetAuthenticationInfo() 方法:用来验证当前登录的用户,获取认证信息。
doGetAuthorizationInfo() 方法:为当前登录成功的用户授予权限和分配角色。

  1. 从数据库查询数据

在数据库中查询登陆人信息的时候,仅仅需要查询用户的id,这时还未涉及到密码,也就是说即使用户输入的密码不正确,照样可以查询出该用户。
然后,将该用户的相关信息封装到authcInfo中并返回给Shiro接下来就该Shiro上场了,将封装的用户信息与用户的输入信息(用户名、密码)进行对比、校验(注意,这里对密码也要进行校验)。校验通过则允许用户登录,否则跳转到指定页面。

4、Shiro配置

  1. 在ShiroConfig中配置Realm
1
2
3
4
@Bean(name="MyRealm")
public MyRealm myRealm() {
return new MyRealm();
}
  1. 配置安全管理器SecurityManager
1
2
3
4
5
6
7
@Bean(name="securityManager")
public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("MyRealm") MyRealm myRealm) {
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
//关联Realm
securityManager.setRealm(myRealm);
return securityManager;
}

当我们配置安全管理器的时候,需要将前面的Realm添加进来,这样子才可以访问到Realm

  1. 配置Shiro过滤器

shiro中自带好了配置的过滤器,我们在使用之前需要将其进行导入

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
//设置安全管理器
shiroFilterFactoryBean.setSecurityManager(securityManager);
//添加Shiro内置过滤器
/*
Shiro内置过滤器,可以实现权限相关的拦截器
常用的有:
anon:无需认证就能访问
authc:必须认证才能访问
user:必须拥有 “记住我” 功能才能使用
perms:拥有对某个资源的权限才能访问
role: 拥有对某个角色权限才能访问
*/
LinkedHashMap<String, String> filterMap = new LinkedHashMap<String,String>();
//这里我们要将不进行拦截的放在前面
filterMap.put("/login", "anon");
filterMap.put("/*", "authc");

//最后设置验证失败的时候所跳转的界面
shiroFilterFactoryBean.setLoginUrl("/toLogin");

此时当我们未登陆的时候,点击被拦截的模块,就会跳到我们所指定的网页,而没有拦截的网页则可以正常显示。