Shiro 十分钟教程

Posted by jiangydev on December 17, 2017

[TOC]

Get Start with Apache Shiro 2

Apache Shiro 十分钟教程

Shiro 能运行在任何环境,从简单的命令行应用程序到最大的企业级 web 和集群应用程序。

Download

  1. 要求:JDK 1.6+, Maven 3.0.3+

  2. 下载 shiro-root-x.x.x-source-release.zip ( Shiro 官方下载页) 并解压

  3. samples\quickstart\ 目录下执行 mvn compile exec:java, 对项目进行编译。

Analysis

  1. Quickstart.java 文件
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
public static void main(String[] args) {

  // 最简单的方式是使用配置了域、用户、角色和权限的 INI 配置文件来创建一个 Shiro SecurityManager. (我们使用 Factory 获取 .ini 文件并返回一个 SecurityManager 实例)
  // 这里使用 classpath 下的 shiro.ini,(path: src\main\resources\shiro.ini)
  // (file: and url: prefixes load from files and urls respectively):
  Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro.ini");
  SecurityManager securityManager = factory.getInstance();

  // 这里,我们设置 SecurityManager,可以理解成一个 JVM 单例。
  // 大多数应用程序不采用这种方式,而是依赖容器配置或 web.xml,因此你可以做进一步配置。
  SecurityUtils.setSecurityManager(securityManager);

  // 至此,一个简单的 Shiro 环境已经设置好, 接下来可以做的是:

  // 获取当前执行的用户:
  Subject currentUser = SecurityUtils.getSubject();

  // 用 Session 做一些事 (不需要 web 或 EJB 容器!!!)
  Session session = currentUser.getSession();
  session.setAttribute("someKey", "aValue");
  String value = (String) session.getAttribute("someKey");
  if (value.equals("aValue")) {
      log.info("Retrieved the correct value! [" + value + "]");
  }

  // 登录当前用户,这样我们可以检查角色和权限:
  if (!currentUser.isAuthenticated()) {
      UsernamePasswordToken token = new UsernamePasswordToken("lonestarr", "vespa");
      token.setRememberMe(true);
      try {
          currentUser.login(token);
      } catch (UnknownAccountException uae) {
          log.info("There is no user with username of " + token.getPrincipal());
      } catch (IncorrectCredentialsException ice) {
          log.info("Password for account " + token.getPrincipal() + " was incorrect!");
      } catch (LockedAccountException lae) {
          log.info("The account for username " + token.getPrincipal() + " is locked.  " +
                  "Please contact your administrator to unlock it.");
      }
      // ... 在这捕获更多异常 (可以为你的应用程序自定义异常)
      catch (AuthenticationException ae) {
          // 处理异常
      }
  }

  //say who they are:
  // 输出用户的身份认证主体 (in this case, a username):
  log.info("User [" + currentUser.getPrincipal() + "] logged in successfully.");

  // 测试角色:
  if (currentUser.hasRole("schwartz")) {
      log.info("May the Schwartz be with you!");
  } else {
      log.info("Hello, mere mortal.");
  }

  // 测试类型权限 (非实例级别)
  if (currentUser.isPermitted("lightsaber:weild")) {
      log.info("You may use a lightsaber ring.  Use it wisely.");
  } else {
      log.info("Sorry, lightsaber rings are for schwartz masters only.");
  }

  // 一个非常有效的实例级别权限:
  if (currentUser.isPermitted("winnebago:drive:eagle5")) {
      log.info("You are permitted to 'drive' the winnebago with license plate (id) 'eagle5'.  " +
              "Here are the keys - have fun!");
  } else {
      log.info("Sorry, you aren't allowed to drive the 'eagle5' winnebago!");
  }

  // 所有的做完之后,退出登录
  // 移除所有身份认证信息并使 Session 无效
  currentUser.logout();

  System.exit(0);
}

尽管有一些复杂的东西,在这个罩下,工作如此优雅。

Q: 但是谁负责在登录期间获取用户数据 (名和密码、角色和权限等), 以及谁在运行时实际执行这些安全检查?

A: 通过实现 Shiro 所谓的 Realm 并将 Realm 塞进 Shiro 的配置。