一、为什么要了解权限框架
权限管理框架属于系统安全的范畴,权限管理实现对用户访问系统的控制,按照安全规则用户可以访问而且只能访问自己被授权的资源。
目前常见的权限框架有Shiro和Spring Security,本篇文章记录springboot整合shiro,实现简单的权限控制。
二、shiro介绍
Shiro全称是Apache Shiro,是一款灵活、强大的安全框架。方便简洁的处理身份认证、授权、加密等。
shiro的三个组件:
Subject 【主体】:指代当前用户【人、爬虫等】
SecurityManager【安全管理器】:管理所有的Subject、具体安全操作的真正执行者。
Reamls:本质是一个安全的DTO,用于进行权限、认证信息;
通过Subject来进行认证和授权,而Subject又委托给SecurityManager; 需要给Shrio的SecurityManager注入Realm,从而让SecurityManager能得到合法的用户及其权限进行判断。
以下是一个简单的Spring Boot + Shiro
权限管理示例,包含以下步骤:
1. 创建 Spring Boot 项目
可以使用 Spring Initializr(https://start.spring.io/)创建一个新的 Spring Boot 项目,添加Web
和thymeleaf
依赖(用于示例中的简单页面展示)
2. 添加 Shiro 依赖
在pom.xml
文件中添加 Shiro 相关依赖
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring-boot-web-starter</artifactId>
<version>1.7.1</version>
</dependency>
3. 创建实体类用户实体类(User)
public class User {
private Long id;
private String username;
private String password;
// 可以添加更多用户相关的属性,如角色列表等
// 构造函数、Getter和Setter方法
public User() {}
public User(String username, String password) {
this.username = username;
this.password = password;
}
// Getter和Setter方法
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
4. 创建 Shiro 配置类
@Configuration
public class ShiroConfig {
@Bean
public ShiroFilterFactoryBean shiroFilterFactoryBean(DefaultWebSecurityManager securityManager) {
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
shiroFilterFactoryBean.setSecurityManager(securityManager);
// 配置登录页面
shiroFilterFactoryBean.setLoginUrl("/login");
// 配置未授权访问页面
shiroFilterFactoryBean.setUnauthorizedUrl("/unauthorized");
// 配置过滤器链
Map<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
// 对静态资源放行
filterChainDefinitionMap.put("/css/**", "anon");
filterChainDefinitionMap.put("/js/**", "anon");
// 登录页面放行
filterChainDefinitionMap.put("/login", "anon");
// 其他请求需要认证
filterChainDefinitionMap.put("/**", "authc");
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
return shiroFilterFactoryBean;
}
@Bean
public DefaultWebSecurityManager securityManager() {
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
securityManager.setRealm(userRealm());
return securityManager;
}
@Bean
public UserRealm userRealm() {
return new UserRealm();
}
}
5. 创建自定义 Realm
public class UserRealm extends AuthorizingRealm {
// 模拟用户数据存储,可以替换为数据库查询
private Map<String, User> userMap = new HashMap<>();
public UserRealm() {
userMap.put("user1", new User("user1", "password1"));
userMap.put("admin", new User("admin", "adminpassword"));
}
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
// 这里可以根据用户角色等信息添加权限,示例简单处理
if ("admin".equals(principals.getPrimaryPrincipal())) {
authorizationInfo.addRole("admin");
}
return authorizationInfo;
}
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
UsernamePasswordToken usernamePasswordToken = (UsernamePasswordToken) token;
String username = usernamePasswordToken.getUsername();
User user = userMap.get(username);
if (user == null) {
throw new UnknownAccountException("用户不存在");
}
return new SimpleAuthenticationInfo(user.getUsername(), user.getPassword(), getName());
}
}
6. 创建控制器(Controller)
@Controller
public class LoginController {
@PostMapping("/login")
public String login(String username, String password, Model model) {
Subject subject = SecurityUtils.getSubject();
UsernamePasswordToken token = new UsernamePasswordToken(username, password);
try {
subject.login(token);
return "redirect:/index";
} catch (AuthenticationException e) {
model.addAttribute("error", "用户名或密码错误");
return "login";
}
}
@GetMapping("/login")
public String showLoginPage() {
return "login";
}
@GetMapping("/unauthorized")
public String unauthorized() {
return "unauthorized";
}
@GetMapping("/index")
public String index() {
return "index";
}
}
前端页面大家可以自己去实现了。
总结:实现了一个简单的Spring Boot + Shiro
权限管理系统,用户可以登录,并且根据角色(这里简单示例了普通用户和管理员)显示不同的内容。在实际应用中,需要将用户数据存储替换为数据库操作,并完善权限管理的逻辑。