Shiro 是一个强大且灵活的 Java 安全框架,用于身份验证、授权、加密和会话管理。在 Spring Boot 中使用 Shiro 可以提供很好的安全保障。为了提高 Shiro 在 Spring Boot 中的稳定性,你可以考虑以下几个方面的优化和配置:
1. 依赖管理
确保你使用的 Shiro 和 Spring Boot 版本是兼容的。你可以使用 Maven 或 Gradle 来管理依赖,并指定正确的版本。
Maven 示例:
org.apache.shiro shiro-spring-boot-starter 1.8.0
Gradle 示例:
implementation 'org.apache.shiro:shiro-spring-boot-starter:1.8.0'
2. 配置优化
在 application.yml
或 application.properties
中进行合理的配置,以确保 Shiro 的稳定运行。
application.yml 示例:
shiro: securityManager: realms: - myRealm myRealm: type: customRealm authenticationStrategy: org.apache.shiro.authc.credential.HashedCredentialsMatcher credentialsMatcher: algorithmName: SHA-256 loginUrl: /login successUrl: /home unauthorizedUrl: /unauthorized
3. 自定义 Realm
实现自定义的 Realm,以便更好地控制身份验证和授权逻辑。
CustomRealm 示例:
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 java.util.HashSet; import java.util.Set; public class CustomRealm extends AuthorizingRealm { @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) { String username = (String) principals.getPrimaryPrincipal(); // 查询用户权限并设置到 SimpleAuthorizationInfo 中 Setroles = getRolesForUser(username); SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo(); authorizationInfo.setRoles(roles); return authorizationInfo; } @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { UsernamePasswordToken upToken = (UsernamePasswordToken) token; String username = upToken.getUsername(); // 查询用户信息并返回 AuthenticationInfo User user = getUserByUsername(username); if (user == null) { throw new UnknownAccountException("用户不存在"); } return new SimpleAuthenticationInfo(user.getUsername(), user.getPassword(), getName()); } private Set getRolesForUser(String username) { // 查询用户角色并返回 return new HashSet<>(); } private User getUserByUsername(String username) { // 查询用户信息并返回 return new User(); } }
4. 会话管理
合理配置会话管理,确保会话的创建、维护和销毁都符合应用需求。
application.yml 示例:
shiro: sessionManager: globalSessionTimeout: 1800000 # 30 minutes
5. 异常处理
自定义异常处理器,以便更好地处理 Shiro 相关的异常。
GlobalExceptionHandler 示例:
import org.apache.shiro.authc.AuthenticationException; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.servlet.ModelAndView; @ControllerAdvice public class GlobalExceptionHandler { @ExceptionHandler(AuthenticationException.class) public ModelAndView handleAuthenticationException(AuthenticationException ex) { ModelAndView modelAndView = new ModelAndView("error"); modelAndView.addObject("message", ex.getMessage()); return modelAndView; } }
6. 测试
编写单元测试和集成测试,确保 Shiro 在各种场景下的稳定性和正确性。
测试示例:
import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; import org.springframework.security.test.context.support.WithMockUser; import org.springframework.test.web.servlet.MockMvc; import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.user; import static org.springframework.security.test.web.servlet.response.SecurityMockMvcResultMatchers.authenticated; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @WebMvcTest(UserController.class) public class UserControllerTest { @Autowired private MockMvc mockMvc; @Test @WithMockUser(username = "admin", roles = "ADMIN") public void testGetHomePage() throws Exception { mockMvc.perform(get("/home")) .andExpect(status().isOk()) .andExpect(authenticated().withRoles("ADMIN")); } }
通过以上步骤,你可以提高 Shiro 在 Spring Boot 中的稳定性,确保其安全性和可靠性。