在现代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应用程序的安全性。希望本文对你有所帮助,如果你有任何问题或建议,请随时留言。