在现代Web应用程序开发中,安全性是一个至关重要的方面。Shiro是一个强大的Java安全框架,提供了身份验证、授权、密码存储和会话管理等功能。本文将详细介绍如何在Spring Boot项目中集成Shiro,以实现授权功能。
一、项目准备
首先,我们需要创建一个Spring Boot项目。你可以使用Spring Initializr或者你喜欢的IDE(如IntelliJ IDEA)来创建一个新的Spring Boot项目。
二、添加Maven依赖
在pom.xml
文件中添加Shiro相关的依赖。这里有两种方式:
- 使用
shiro-spring
依赖:
<dependency> | |
<groupId>org.apache.shiro</groupId> | |
<artifactId>shiro-spring</artifactId> | |
<version>1.3.2</version> | |
</dependency> |
- 使用
shiro-spring-boot-web-starter
依赖(更简便):
<dependency> | |
<groupId>org.apache.shiro</groupId> | |
<artifactId>shiro-spring-boot-web-starter</artifactId> | |
<version>1.4.2</version> | |
</dependency> |
三、配置Shiro
在Spring Boot项目中,我们通常使用application.yml
或application.properties
文件来配置Shiro。以下是一个简单的application.yml
配置示例:
spring: | |
profiles: | |
active: dev | |
mybatis: | |
mapper-locations: classpath:mapper/*Mapper.xml | |
server: | |
port: 8080 | |
shiro: | |
web: | |
enabled: true | |
loginUrl: /login |
四、创建Shiro配置类
Shiro配置类用于配置Shiro的SecurityManager
和自定义的Realm
。以下是一个示例:
import org.apache.shiro.mgt.DefaultWebSecurityManager; | |
import org.apache.shiro.spring.web.ShiroFilterFactoryBean; | |
import org.apache.shiro.spring.web.config.DefaultShiroFilterChainDefinition; | |
import org.apache.shiro.spring.web.config.ShiroFilterChainDefinition; | |
import org.apache.shiro.web.mgt.DefaultWebSubjectFactory; | |
import org.springframework.context.annotation.Bean; | |
import org.springframework.context.annotation.Configuration; | |
import javax.servlet.Filter; | |
import java.util.LinkedHashMap; | |
import java.util.Map; | |
@Configuration | |
public class ShiroConfig { | |
@Bean | |
public UserRealm userRealm() { | |
return new UserRealm(); | |
} | |
@Bean | |
public DefaultWebSecurityManager securityManager(UserRealm userRealm) { | |
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(); | |
securityManager.setRealm(userRealm); | |
securityManager.setSubjectFactory(new DefaultWebSubjectFactory()); | |
return securityManager; | |
} | |
@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("/login", "anon"); | |
filterChainDefinitionMap.put("/doLogin", "anon"); | |
filterChainDefinitionMap.put("/admin/**", "authc, roles[admin]"); | |
filterChainDefinitionMap.put("/docs/**", "authc, perms[document:read]"); | |
filterChainDefinitionMap.put("/**", "authc"); | |
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap); | |
return shiroFilterFactoryBean; | |
} | |
} |
五、创建自定义Realm
自定义Realm用于处理身份验证和授权逻辑。以下是一个示例:
import org.apache.shiro.authc.*; | |
import org.apache.shiro.authz.AuthorizationInfo; | |
import org.apache.shiro.authz.SimpleAuthorizationInfo; | |
import org.apache.shiro.realm.AuthorizingRealm; | |
import org.apache.shiro.subject.PrincipalCollection; | |
import org.springframework.beans.factory.annotation.Autowired; | |
public class UserRealm extends AuthorizingRealm { | |
@Autowired | |
private UserService userService; | |
@Override | |
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) { | |
String username = (String) principalCollection.getPrimaryPrincipal(); | |
User user = userService.findByUsername(username); | |
SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo(); | |
authorizationInfo.setRoles(user.getRoles()); | |
authorizationInfo.setStringPermissions(user.getPermissions()); | |
return authorizationInfo; | |
} | |
@Override | |
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException { | |
UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken; | |
String username = token.getUsername(); | |
User user = userService.findByUsername(username); | |
if (user == null) { | |
throw new UnknownAccountException("用户不存在"); | |
} | |
SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo( | |
username, | |
user.getPassword(), | |
getName() | |
); | |
return authenticationInfo; | |
} | |
} |
六、实现授权功能
在自定义Realm中,我们已经实现了授权逻辑。现在,我们需要在控制器中使用Shiro的注解来实现授权控制。
import org.apache.shiro.authz.annotation.RequiresPermissions; | |
import org.apache.shiro.authz.annotation.RequiresRoles; | |
import org.springframework.web.bind.annotation.GetMapping; | |
import org.springframework.web.bind.annotation.RequestMapping; | |
import org.springframework.web.bind.annotation.RestController; | |
@RestController | |
@RequestMapping("/admin") | |
public class AdminController { | |
@GetMapping("/dashboard") | |
@RequiresRoles("admin") | |
public String dashboard() { | |
return "Admin Dashboard"; | |
} | |
@GetMapping("/docs") | |
@RequiresPermissions("document:read") | |
public String docs() { | |
return "Documents"; | |
} | |
} |
七、测试授权功能
启动Spring Boot应用程序,并访问不同的URL来测试授权功能。例如:
- 访问
/admin/dashboard
,应该要求登录,并且只有具有admin
角色的用户才能访问。 - 访问
/docs
,应该要求登录,并且只有具有document:read
权限的用户才能访问。
八、总结
通过本文,我们详细介绍了如何在Spring Boot项目中集成Shiro并实现授权功能。Shiro提供了强大的安全功能,可以大大提高Web应用程序的安全性。希望本文对你有所帮助,如果你有任何问题或建议,请随时留言。