• 概念: Apache Shiro 是一个强大且易用的 Java 安全框架
  • 能做什么:Shiro可以帮我们完成 :认证授权、加密、会话管理、与 Web 集成、缓存等。

20201202215335331.png
主要认识:

  • Subject(用户):

当前的操作用户 获取当前用户Subject currentUser = SecurityUtils.getSubject()

  • SecurityManager(安全管理器):

Shiro的核心,负责与其他组件进行交互,实现 subject 委托的各种功能

  • Realms(数据源) :

Realm会查找相关数据源,充当与安全管理间的桥梁,经过Realm找到数据源进行认 证,授权等操作

  • Authenticator(认证器):

用于认证,从 Realm 数据源取得数据之后进行执行认证流程处理。

  • Authorizer(授权器):

用户访问控制授权,决定用户是否拥有执行指定操作的权限。

  • SessionManager (会话管理器): 支持会话管理
  • CacheManager (缓存管理器): 用于缓存认证授权信息
  • Cryptography(加密组件): 提供了加密解密的工具包

    认证的关键对象:

    Subject:主体

    访问系统的用户,主体可以是用户、程序等,进行认证的都称为主体

    Principal:身份信息

    身份信息,是主体(subject)进行身份认证的标识,标识必须具有唯一性,如用户名、手机号、邮箱地址等,一个主体可以有多个身份,但是必须有一个主身份(Primary Principal)

    credential:凭证信息

    凭证信息,是只有主体自己知道的安全信息,如密码、证书等

    认证流程

    image.png
    image.png
    将用户(主体)的用户名(身份信息)和密码(凭证信息)封装成Token(令牌)对象给到安全管理器进行校验 ```xml org.apache.shiro shiro-core 1.5.3
  1. <a name="vgEHU"></a>
  2. ##### 常见的异常类型
  3. - DisabledAccountException(帐号被禁用)
  4. - LockedAccountException(帐号被锁定)
  5. - ExcessiveAttemptsException(登录失败次数过多)
  6. - ExpiredCredentialsException(凭证过期)等
  7. <a name="WsqgG"></a>
  8. ### 认证代码
  9. ```java
  10. //1.创建安全管理器对象
  11. DefaultSecurityManager securityManager = new DefaultSecurityManager();
  12. //2.给安全管理器设置realm
  13. securityManager.setRealm(new IniRealm("classpath:shiro.ini"));
  14. //3.SecurityUtils给全局安全工具类设置安全管理器
  15. SecurityUtils.setSecurityManager(securityManager);
  16. //4.关键对象subject主体
  17. Subject subject = SecurityUtils.getSubject();
  18. //5.创建令牌
  19. UsernamePasswordToken token = new UsernamePasswordToken("zax","123456");
  20. try {
  21. System.out.println("认证状态"+subject.isAuthenticated());//fasle
  22. //用户认证
  23. subject.login(token);
  24. System.out.println("认证状态"+subject.isAuthenticated());
  25. }catch (UnknownAccountException e){
  26. e.printStackTrace();
  27. System.out.println("认证失败,用户名不存在");
  28. }catch (IncorrectCredentialsException e){
  29. e.printStackTrace();
  30. System.out.println("认证失败,密码错误");
  31. }

image.pnge9229269698a66b32a74812fa6ddaa7d.pngSimpleAccountRealm的部分源码中有两个方法一个是 认证 一个是 授权

MD5+salt+hash散列

  1. //使用md5
  2. Md5Hash md5Hash = new Md5Hash("123");
  3. System.out.println(md5Hash.toHex());
  4. //使用MD5 + salt处理
  5. Md5Hash md5Hash1 = new Md5Hash("123", "X0*7ps");
  6. System.out.println(md5Hash1.toHex());
  7. //使用md5 + salt + hash散列(参数代表要散列多少次,一般是 1024或2048)
  8. Md5Hash md5Hash2 = new Md5Hash("123", "X0*7ps", 1024);
  9. System.out.println(md5Hash2.toHex());

自定义Realm类

  1. package com.kgc.dmeo.test;
  2. import com.kgc.dmeo.entity.User;
  3. import com.kgc.dmeo.service.UserService;
  4. import org.apache.shiro.authc.AuthenticationException;
  5. import org.apache.shiro.authc.AuthenticationInfo;
  6. import org.apache.shiro.authc.AuthenticationToken;
  7. import org.apache.shiro.authc.SimpleAuthenticationInfo;
  8. import org.apache.shiro.authz.AuthorizationInfo;
  9. import org.apache.shiro.realm.AuthorizingRealm;
  10. import org.apache.shiro.subject.PrincipalCollection;
  11. import org.apache.shiro.util.ByteSource;
  12. import org.springframework.beans.factory.annotation.Autowired;
  13. import org.springframework.stereotype.Component;
  14. /**
  15. * 自定义Realm
  16. */
  17. @Component
  18. public class CustomerRealm extends AuthorizingRealm {
  19. @Autowired(required = false)
  20. private UserService userService;
  21. //授权
  22. @Override
  23. protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
  24. return null;
  25. }
  26. @Override
  27. protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
  28. //获取 token中的 用户名
  29. String principal = (String) token.getPrincipal();
  30. //假设这是从数据库查询到的信息
  31. // String username="zhangsan";
  32. // String password="7268f6d32ec8d6f4c305ae92395b00e8";//加密后
  33. User user = userService.getUserById(principal);
  34. //根据用户名查询数据库
  35. // username.equals(principal)
  36. if (user!=null) {
  37. //参数1:数据库用户名
  38. //参数2:数据库md5+salt之后的密码
  39. //参数3:注册时的随机盐
  40. //参数4:realm的名字
  41. return new SimpleAuthenticationInfo(principal,
  42. user.getPassword(),
  43. ByteSource.Util.bytes(user.getSalt()),
  44. this.getName());
  45. }
  46. return null;
  47. }
  48. }
  1. //1.创建安全管理器
  2. DefaultSecurityManager defaultSecurityManager = new DefaultSecurityManager();
  3. //2.注入realm
  4. CustomerRealm realm = SpringUtil.getBean(CustomerRealm.class);
  5. //3.设置realm使用hash凭证匹配器
  6. HashedCredentialsMatcher credentialsMatcher = new HashedCredentialsMatcher();
  7. //声明:使用的算法
  8. credentialsMatcher.setHashAlgorithmName("md5");
  9. //声明:散列次数
  10. credentialsMatcher.setHashIterations(1024);
  11. //设置凭证匹配器
  12. realm.setCredentialsMatcher(credentialsMatcher);
  13. //将realm放入安全管理器中
  14. defaultSecurityManager.setRealm(realm);
  15. //4.将安全管理器注入安全工具
  16. SecurityUtils.setSecurityManager(defaultSecurityManager);
  17. //5.通过安全工具类获取subject
  18. Subject subject = SecurityUtils.getSubject();
  19. //6.认证
  20. UsernamePasswordToken token = new UsernamePasswordToken("12121", "123");
  21. try {
  22. subject.login(token);
  23. System.out.println("登录成功");
  24. } catch (UnknownAccountException e) {
  25. e.printStackTrace();
  26. System.out.println("用户名错误");
  27. } catch (IncorrectCredentialsException e) {
  28. e.printStackTrace();
  29. System.out.println("密码错误");
  30. }

授权

授权,即访问控制,控制谁能访问哪些资源。主体进行身份认证后需要分配权限方可访问系统的资源,对于某些资源没有权限是无法访问的。
image.png
2776d1da95d468069505ec23d87fe23e.png

授权方式

image.png
shiro提供和多个默认的过滤器,我们可以用这些过滤器来配置控制指定url的权限:
image.png