shiro简单使用

之前做的一个项目用到了shiro这个工具,用它来做权限管理十分方便。本文记录一下它的简单用法。

依赖配置

首先maven导入shiro依赖

1
2
3
4
5
6
<!-- shiro -->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring-boot-starter</artifactId>
<version>1.4.0</version>
</dependency>

添加Shiro配置类

接下来需要一个config类来进行shiro的各种配置。下面提供一个最精简的配置模板。

源码戳这里

UserRealm类简介

之后就需要实现最重要的类UserRealm。这个类提供两个方法,他们的名字非常相似,但是功能完全不同。

第一个方法是doGetAuthenticationInfo(注意是Authentication,中文是鉴定)。顾名思义,这个方法的作用是进行登录验证,同时返回登录的信息。该方法在用户登录时调用。

第二个方法叫做doGetAuthorizationInfo(注意是Authorization,中文是授权)。顾名思义,这个方法的作用是对用户进行授权,这也是shiro实现权限管理的核心功能。该方法在涉及用户权限的操作时调用。比如subject.hasRole()。

验证方法

来看一个doGetAuthenticationInfo的实例。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
// get username
String userName = (String) authenticationToken.getPrincipal();
// get password
String password = new String((char[])authenticationToken.getCredentials());

if (userName == null) {
throw new UnknownAccountException();
} else if (!password.equals(user.getPassword()))
throw new IncorrectCredentialsException();

// pass authentication information
return new SimpleAuthenticationInfo(userName, password, getName());;
}

在看和它配套的用户登录部分的代码

1
2
3
4
5
6
7
8
9
UsernamePasswordToken token = new UsernamePasswordToken(username, password);
Subject subject = SecurityUtils.getSubject();
try {
subject.login(token); // where the doGetAuthenticationInfo is called
} catch (Exception e) {
model.addAttribute("message","Invalid Credential");
// if unsuccessful
return "redirect:/login";
}

授权方法

来看一个doGetAuthorizationInfo的实例。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
// get userName
String userName = (String) getAvailablePrincipal(principalCollection);
// find user by name
User user = userService.findUserByName(userName);
// get the user role
Role role = user.getRole();
// get user permissions
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
Set<String> roles = new HashSet<>();
if (role != null) {
roles.add(role.getName());
info.setRoles(roles);
}

return info;
}

你可能会好奇principleCollection是从哪里得到的。其实就是我们在authentication里面return的那个信息类。之前我们调用的是

1
return new SimpleAuthenticationInfo(userName, password, getName());;

所以这里

1
(String) getAvailablePrincipal(principalCollection);

得到也是username.

如果我们return一个user对象

1
return new SimpleAuthenticationInfo(user, password, getName());;

那我们就可以用同样的方法get到一个user对象。

最后看下配套的controller权限管理方法。

1
2
3
4
5
6
if (subject.hasRole("admin"))
return "redirect:/admin/adminHome";
else if (subject.hasRole("teacher"))
return "redirect:/teacher/teacherHome";
else if (subject.hasRole("student"))
return "redirect:/student/studentHome";

当我们调用subject.hasRole时,doGetAuthorizationInfo 将被调用,返回用户的权限信息。