自定义Realm需要继承AuthorizingRealm类,并重写doGetAuthenticationInfo(登录认证)和doGetAuthorizationInfo(权限认证)方法。创建下面三张表。
用户表:
权限表:
用户表与权限表的关系表
代码如下所示,关于查询的数据库的代码、表结构的SQL,都去看案例文件。
/**
* 自定义Realm,需要注入到Spring IoC中
*/
@Component
public class MyRealm extends AuthorizingRealm {
@Autowired
private UsersMapper usersMapper;
@Autowired
private UserRolesPermissionsMapper userRolesPermissionsMapper;
public MyRealm() {
super.setName("MyRealm");//设置Realm的名字
}
/**
* 完成登录认证的方法
*
* @param authenticationToken
* @return
* @throws AuthenticationException
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
// 获取账号信息
String username = (String) authenticationToken.getPrincipal();
String password = usersMapper.getPasswordByUsername(username);
if (password == null)
throw new AuthenticationException("该账号不存在,验证失败");
// 验证密码,密码验证shiro已经实现,只用给shiro传入正确的密码就好,第三个参数传入的是Realm的类名
AuthenticationInfo info = new SimpleAuthenticationInfo(username, password, "MyRealm");
return info;
}
/**
* 辅助完成用户权限检查的方法,用于查出用户的角色和权限
*
* @param principalCollection
* @return
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
String username = (String) principalCollection.getPrimaryPrincipal();
//账号传入为空就返回一个空
if (username == null)
return null;
//查询出这个账号的角色和权限
List<String> permissionsList = userRolesPermissionsMapper.getPermissionsListByUsername(username);
List<String> roleList = userRolesPermissionsMapper.getRolesListByUsername(username);
//组装返回数据
SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
simpleAuthorizationInfo.addRoles(roleList);
simpleAuthorizationInfo.addStringPermissions(permissionsList);
return simpleAuthorizationInfo;
}
}
控制器代码:
@RestController
public class Test {
@Autowired
private MyRealm myRealm;
@GetMapping("/test")
public Object test(String username, String password) {
try {
//1:构建securityManager环境
DefaultSecurityManager defaultSecurityManager = new DefaultSecurityManager();
defaultSecurityManager.setRealm(myRealm);
//2:主体提交认证请求
SecurityUtils.setSecurityManager(defaultSecurityManager);
Subject subject = SecurityUtils.getSubject();
//3:登录(Shiro接管了登录功能)
UsernamePasswordToken token = new UsernamePasswordToken(username, password);
subject.login(token);
//3:检查当前用户是否有指定权限,检查对当用户是不是指定角色
subject.checkPermissions("user:save", "user:update");
subject.checkRoles("admin");
//查看认证结果
return "认证结果:" + subject.isAuthenticated();
} catch (Exception e) {
return "认证结果:" + e;
}
}
}
调用控制器并传入参数
http://127.0.0.1:8181/test?username=hello&password=123456
如果我多验证一个”user:delete”权限,就会报错提示当前用户没有该权限。
SQL:
/*
SQLyog Ultimate v12.4.1 (64 bit)
MySQL - 8.0.14 : Database - shiro
*********************************************************************
*/
/*Table structure for table `roles_permissions` */
DROP TABLE IF EXISTS `roles_permissions`;
CREATE TABLE `roles_permissions` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键id',
`role_name` varchar(32) NOT NULL COMMENT '角色名称',
`permission` varchar(32) NOT NULL COMMENT '角色权限',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8 COMMENT='角色表';
/*Data for the table `roles_permissions` */
insert into `roles_permissions`(`id`,`role_name`,`permission`) values
(1,'member','user:list'),
(2,'member','user:update'),
(3,'admin','user:update'),
(4,'admin','user:save'),
(5,'admin','user:list'),
(6,'superAdminRole','user:update'),
(7,'superAdminRole','user:delete'),
(8,'superAdminRole','user:save'),
(9,'superAdminRole','user:list');
/*Table structure for table `user_roles` */
DROP TABLE IF EXISTS `user_roles`;
CREATE TABLE `user_roles` (
`id` bigint(2) NOT NULL AUTO_INCREMENT COMMENT '主键',
`username` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '账号',
`role_name` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '角色名称',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8 COMMENT='用户与角色关系表';
/*Data for the table `user_roles` */
insert into `user_roles`(`id`,`username`,`role_name`) values
(1,'hello','admin'),
(2,'hello','member');
/*Table structure for table `users` */
DROP TABLE IF EXISTS `users`;
CREATE TABLE `users` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键id',
`username` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '账号',
`password` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '密码',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8 COMMENT='用户表';
/*Data for the table `users` */
insert into `users`(`id`,`username`,`password`) values
(1,'hello','123456');