跟认证过程大致相似,下面我们仍然通过代码来熟悉一下过程(引入包类似这里节约篇幅就不贴出来了):
public class AuthenticationTest {
SimpleAccountRealm simpleAccountRealm = new SimpleAccountRealm();
@Before // 在方法开始前添加一个用户,让它具备admin和user两个角色
public void addUser() {
simpleAccountRealm.addAccount("wmyskxz", "123456", "admin", "user");
}
@Test
public void testAuthentication() {
// 1.构建SecurityManager环境
DefaultSecurityManager defaultSecurityManager = new DefaultSecurityManager();
defaultSecurityManager.setRealm(simpleAccountRealm);
// 2.主体提交认证请求
SecurityUtils.setSecurityManager(defaultSecurityManager); // 设置SecurityManager环境
Subject subject = SecurityUtils.getSubject(); // 获取当前主体
UsernamePasswordToken token = new UsernamePasswordToken("wmyskxz", "123456");
subject.login(token); // 登录
// subject.isAuthenticated()方法返回一个boolean值,用于判断用户是否认证成功
System.out.println("isAuthenticated:" + subject.isAuthenticated()); // 输出true
// 判断subject是否具有admin和user两个角色权限,如没有则会报错
subject.checkRoles("admin","user");
// subject.checkRole("xxx"); // 报错
}
}
运行测试,能够正确看到效果。
自定义 Realm
从上面我们了解到实际进行权限信息验证的是我们的 Realm,Shiro 框架内部默认提供了两种实现,一种是查询.ini
文件的IniRealm
,另一种是查询数据库的JdbcRealm
,这两种来说都相对简单,感兴趣的可以去【这里】瞄两眼,我们着重就来介绍介绍自定义实现的 Realm 吧。
有了上面的对认证和授权的理解,我们先在合适的包下创建一个【MyRealm】类,继承 Shirot 框架的 AuthorizingRealm 类,并实现默认的两个方法:
package com.wmyskxz.demo.realm;
import org.apache.shiro.authc.*;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import java.util.*;
public class MyRealm extends AuthorizingRealm {
/**
* 模拟数据库数据
*/
Map<String, String> userMap = new HashMap<>(16);
{
userMap.put("wmyskxz", "123456");
super.setName("myRealm"); // 设置自定义Realm的名称,取什么无所谓..
}
/**
* 授权
*
* @param principalCollection
* @return
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
String userName = (String) principalCollection.getPrimaryPrincipal();
// 从数据库获取角色和权限数据
Set<String> roles = getRolesByUserName(userName);
Set<String> permissions = getPermissionsByUserName(userName);
SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
simpleAuthorizationInfo.setStringPermissions(permissions);
simpleAuthorizationInfo.setRoles(roles);
return simpleAuthorizationInfo;
}
/**
* 模拟从数据库中获取权限数据
*
* @param userName
* @return
*/
private Set<String> getPermissionsByUserName(String userName) {
Set<String> permissions = new HashSet<>();
permissions.add("user:delete");
permissions.add("user:add");
return permissions;
}
/**
* 模拟从数据库中获取角色数据
*
* @param userName
* @return
*/
private Set<String> getRolesByUserName(String userName) {
Set<String> roles = new HashSet<>();
roles.add("admin");
roles.add("user");
return roles;
}
/**
* 认证
*
* @param authenticationToken 主体传过来的认证信息
* @return
* @throws AuthenticationException
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
// 1.从主体传过来的认证信息中,获得用户名
String userName = (String) authenticationToken.getPrincipal();
// 2.通过用户名到数据库中获取凭证
String password = getPasswordByUserName(userName);
if (password == null) {
return null;
}
SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo("wmyskxz", password, "myRealm");
return authenticationInfo;
}
/**
* 模拟从数据库取凭证的过程
*
* @param userName
* @return
*/
private String getPasswordByUserName(String userName) {
return userMap.get(userName);
}
}
然后我们编写测试类,来验证是否正确:
import com.wmyskxz.demo.realm.MyRealm;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.mgt.DefaultSecurityManager;
import org.apache.shiro.subject.Subject;
import org.junit.Test;
public class AuthenticationTest {
@Test
public void testAuthentication() {
MyRealm myRealm = new MyRealm(); // 实现自己的 Realm 实例
// 1.构建SecurityManager环境
DefaultSecurityManager defaultSecurityManager = new DefaultSecurityManager();
defaultSecurityManager.setRealm(myRealm);
// 2.主体提交认证请求
SecurityUtils.setSecurityManager(defaultSecurityManager); // 设置SecurityManager环境
Subject subject = SecurityUtils.getSubject(); // 获取当前主体
UsernamePasswordToken token = new UsernamePasswordToken("wmyskxz", "123456");
subject.login(token); // 登录
// subject.isAuthenticated()方法返回一个boolean值,用于判断用户是否认证成功
System.out.println("isAuthenticated:" + subject.isAuthenticated()); // 输出true
// 判断subject是否具有admin和user两个角色权限,如没有则会报错
subject.checkRoles("admin", "user");
// subject.checkRole("xxx"); // 报错
// 判断subject是否具有user:add权限
subject.checkPermission("user:add");
}
}
运行测试,完美。