下面我将为您详细讲解Spring Boot集成Shiro实现动态加载权限的完整步骤。
一、引入依赖
在Spring Boot项目中,需要引入以下依赖:
<!-- shiro依赖 -->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring-boot-web-starter</artifactId>
<version>1.7.1</version>
</dependency>
<!-- mybatis-plus依赖 -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.2.0</version>
</dependency>
<!-- druid依赖 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.2.5</version>
</dependency>
其中,shiro-spring-boot-web-starter
是Shiro的Spring Boot集成依赖,mybatis-plus-boot-starter
是Mybatis Plus的Spring Boot集成依赖,druid-spring-boot-starter
是Druid连接池的Spring Boot集成依赖。
二、定义Shiro的Realm
在Spring Boot项目中,需要定义一个继承自AuthorizingRealm
的Realm类,用于进行认证和授权操作。示例代码如下:
@Component
public class UserRealm extends AuthorizingRealm {
@Autowired
private UserService userService;
/**
* 认证
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;
String username = token.getUsername();
User user = userService.getUserByUsername(username);
if (user == null) {
throw new UnknownAccountException("账号不存在");
} else {
return new SimpleAuthenticationInfo(user, user.getPassword(), getName());
}
}
/**
* 授权
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
User user = (User) principalCollection.getPrimaryPrincipal();
List<Role> roleList = userService.getRoleListByUserId(user.getId());
Set<String> roleSet = new HashSet<>();
Set<String> permissionSet = new HashSet<>();
for (Role role : roleList) {
roleSet.add(role.getName());
List<Permission> permissionList = userService.getPermissionListByUserIdAndRoleId(user.getId(), role.getId());
for (Permission permission : permissionList) {
permissionSet.add(permission.getName());
}
}
authorizationInfo.setRoles(roleSet);
authorizationInfo.setStringPermissions(permissionSet);
return authorizationInfo;
}
}
以上代码中,doGetAuthenticationInfo
方法用于进行认证操作,根据用户名查询用户并返回认证信息;doGetAuthorizationInfo
方法用于进行授权操作,根据用户的角色和权限进行授权。
三、配置Shiro的过滤器
在Spring Boot项目中,需要配置Shiro的过滤器,来控制用户访问URL的权限。示例代码如下:
@Configuration
public class ShiroConfig {
@Bean
public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager) {
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
shiroFilterFactoryBean.setSecurityManager(securityManager);
// 自定义过滤器,用于动态加载权限
Map<String, Filter> filters = new LinkedHashMap<>();
filters.put("perms", new CustomPermissionsAuthorizationFilter());
shiroFilterFactoryBean.setFilters(filters);
// 定义url过滤规则
Map<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
// 配置不需要权限认证的url
filterChainDefinitionMap.put("/login", "anon");
// 配置需要权限认证的url
filterChainDefinitionMap.put("/**", "perms");
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
return shiroFilterFactoryBean;
}
@Bean
public SecurityManager securityManager(UserRealm userRealm) {
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
securityManager.setRealm(userRealm);
return securityManager;
}
}
其中,定义了一个自定义过滤器CustomPermissionsAuthorizationFilter
,用于动态加载权限,在后面会详细介绍;同时,还定义了url过滤规则,配置了不需要权限认证的url和需要权限认证的url。
四、配置Shiro的权限注解
在Spring Boot项目中,需要在需要控制权限的方法上添加Shiro的注解@RequiresPermissions
。示例代码如下:
@RequiresPermissions("user:view")
@GetMapping("/list")
public Result list(@RequestParam(required = false) String username) {
List<User> userList = userService.getUserList(username);
return Result.success(userList);
}
以上代码中,使用了@RequiresPermissions("user:view")
注解,表示用户需要具备“user:view”权限才能访问该方法。
五、实现动态加载权限
在Spring Boot项目中,实现动态加载权限需要定义一个自定义过滤器CustomPermissionsAuthorizationFilter
。示例代码如下:
public class CustomPermissionsAuthorizationFilter extends PermissionsAuthorizationFilter {
@Autowired
private UserService userService;
@Override
public boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) throws IOException {
Subject subject = getSubject(request, response);
// 获取请求的url
String url = getPathWithinApplication(request);
// 获取当前用户的角色和权限
User user = (User) subject.getPrincipal();
List<Permission> permissionList = userService.getPermissionListByUrlAndUserId(url, user.getId());
Set<String> permissionSet = new HashSet<>();
for (Permission permission : permissionList) {
permissionSet.add(permission.getName());
}
// 判断用户是否具备请求的url所需的权限
return subject.isPermittedAll(permissionSet.toArray(new String[permissionSet.size()]));
}
}
以上代码中,重写了父类的isAccessAllowed
方法,用于实现动态加载权限。首先获取请求的url和当前用户的角色和权限信息,然后根据url和userId查询当前登录用户所具备的权限,最后判断用户是否具备请求的url所需的权限。
六、使用示例
以下是一个获取用户列表的Controller示例:
@RestController
@RequestMapping("/user")
public class UserController {
@Autowired
private UserService userService;
@GetMapping("/list")
@RequiresPermissions("user:view")
public Result list(@RequestParam(required = false) String username) {
List<User> userList = userService.getUserList(username);
return Result.success(userList);
}
@PostMapping("/add")
@RequiresPermissions("user:add")
public Result add(@RequestBody User user) {
userService.addUser(user);
return Result.success();
}
}
其中,@RequiresPermissions("user:view")
和@RequiresPermissions("user:add")
注解用于控制用户访问该方法的权限。
另外,还需要进行登录认证才能访问受控的URL,登录认证代码如下:
@PostMapping("/login")
public Result login(@RequestBody User user) {
UsernamePasswordToken token = new UsernamePasswordToken(user.getUsername(), user.getPassword());
Subject subject = SecurityUtils.getSubject();
try {
subject.login(token);
return Result.success("登录成功");
} catch (AuthenticationException e) {
return Result.error(e.getMessage());
}
}
小结
以上就是Spring Boot集成Shiro实现动态加载权限的完整步骤,包括引入依赖、定义Shiro的Realm、配置Shiro的过滤器、配置Shiro的权限注解以及实现动态加载权限。其中,完成一个自定义过滤器用于动态加载权限是实现该功能的关键所在。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Spring Boot集成Shiro实现动态加载权限的完整步骤 - Python技术站