Shiro安全认证

发布时间 2023-04-28 10:39:24作者: 歆鱼

学习视频:https://www.bilibili.com/video/BV1Wb411V7uk

学习网站:https://www.w3cschool.cn/shiro/

介绍

Apache Shiro 是 Java 的一个安全框架

Shiro 可以完成:认证、授权、加密、会话管理、与 Web 集成、缓存等。

  • Authentication:身份认证 / 登录
  • Authorization:授权,即权限验证
  • Session Management:会话管理
  • Cryptography:加密,
  • Web Support:Web 支持
  • Caching:缓存
  • Concurrency:shiro 支持多线程应用的并发验证
  • Testing:提供测试支持;
  • Run As:允许一个用户假装为另一个用户(如果他们允许)的身份进行访问;
  • Remember Me:记住我

注意:Shiro 不会去维护用户、维护权限;这些需要我们自己去设计 / 提供;然后通过相应的接口注入给 Shiro 即可。

三大功能

1.身份验证

在shiro中,用户需要提供principlas(身份)和credentials(证明)给shiro,从而应用能验证用户身份

a.导入依赖

<dependencies>
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.9</version>
    </dependency>
    <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.2.2</version>
    </dependency>
</dependencies>

b.在resources下创建shiro.ini文件

[users]
zhang=z3
wang=w5

通过 [users] 指定了两个主体:zhang/z3、wang/w5

c.测试

@Test
public void testHelloworld() {
    //1、获取SecurityManager工厂,此处使用Ini配置文件初始化SecurityManager  
    Factory<org.apache.shiro.mgt.SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro.ini");
    //2、得到SecurityManager实例 并绑定给SecurityUtils
    org.apache.shiro.mgt.SecurityManager securityManager = factory.getInstance();
    SecurityUtils.setSecurityManager(securityManager);
    //3、得到Subject及创建用户名/密码身份验证Token(即用户身份/凭证)
    Subject subject = SecurityUtils.getSubject();
    UsernamePasswordToken token = new UsernamePasswordToken("zhang", "z3");
    try {
        //4、登录,即身份验证
        subject.login(token);
    } catch (AuthenticationException e) {
        //5、身份验证失败
    }
    Assert.assertEquals(true, subject.isAuthenticated()); //断言用户已经登录
    //6、退出
    subject.logout();
}

 

2.授权

授权,也叫访问控制,即在应用中控制谁能访问哪些资源(如访问页面/编辑数据/页面操作等)

a.shiro.ini

 

[users]
zhang=123,role1,role2
wang=123,role1
[roles]
role1=user:create,user:update
role2=user:create,user:delete

 

b.测试

      //身份验证
//subject.login(token); login(
"classpath:shiro.ini", "zhang", "123"); //判断拥有角色:role1 Assert.assertTrue(subject().hasRole("role1")); //判断拥有角色:role1 and role2 Assert.assertTrue(subject().hasAllRoles(Arrays.asList("role1", "role2"))); //判断拥有角色:role1 and role2 and !role3 boolean[] result = subject().hasRoles(Arrays.asList("role1", "role2", "role3")); Assert.assertEquals(true, result[0]); Assert.assertEquals(true, result[1]); Assert.assertEquals(false, result[2]); //断言拥有角色:role1 失败抛出异常 subject().checkRoles("role1"); //判断拥有权限:user:create Assert.assertTrue(subject().isPermitted("user:create")); //判断拥有权限:user:update and user:delete Assert.assertTrue(subject().isPermittedAll("user:update", "user:delete")); //判断没有权限:user:view Assert.assertFalse(subject().isPermitted("user:view")); //断言拥有权限:user:view 失败抛出异常 subject().checkPermissions("user:view"); }

 

 

3.加密

//密码明文
String password = "z3";
//使用md5加密
Md5Hash = md5Hash = new Md5Hash(password);
//带盐的md5加密,盐就是在密码明文后凭借新的字符串,然后在进行加密
Md5Hash md5Hash2 = new Md5Hash(password,"salt");
//多次迭代加密
Md5Hash md5Hash3 = new Md5Hash(password,"salt",3);
//使用父类进行加密
SimpleHash simpleHash = new SimpleHash("MD5",password,"salt",3)

//生成 Realm
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
SimpleAuthenticationInfo ai = 
        new SimpleAuthenticationInfo(token.getPrincipal()【用户凭证】, password【加密后的密码】, token.getPrincipal().toString()【用户名】);
    ai.setCredentialsSalt(ByteSource.Util.bytes(username+salt2)); //盐是用户名+随机数
        return ai;
}