Shiro 是一个强大且灵活的 Java 安全框架,用于身份验证、授权、加密和会话管理。在 Spring Boot 中使用 Shiro 可以提供很好的安全保障。为了提高 Shiro 在 Spring Boot 中的稳定性,你可以考虑以下几个方面的优化和配置:
确保你使用的 Shiro 和 Spring Boot 版本是兼容的。你可以使用 Maven 或 Gradle 来管理依赖,并指定正确的版本。
Maven 示例:
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring-boot-starter</artifactId>
<version>1.8.0</version>
</dependency>
Gradle 示例:
implementation 'org.apache.shiro:shiro-spring-boot-starter:1.8.0'
在 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
实现自定义的 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 中
Set<String> roles = 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<String> getRolesForUser(String username) {
// 查询用户角色并返回
return new HashSet<>();
}
private User getUserByUsername(String username) {
// 查询用户信息并返回
return new User();
}
}
合理配置会话管理,确保会话的创建、维护和销毁都符合应用需求。
application.yml 示例:
shiro:
sessionManager:
globalSessionTimeout: 1800000 # 30 minutes
自定义异常处理器,以便更好地处理 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;
}
}
编写单元测试和集成测试,确保 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 中的稳定性,确保其安全性和可靠性。