如何在SpringBoot整合Apache Shiro?

如何在SpringBoot整合Apache Shiro?

经验文章nimo972025-01-06 22:16:5511A+A-

Apache Shiro是一款与Spring Security类似的功能强大的Java安全框架,但相比较于Spring Security,Apache Shiro更加轻量化且易于集成。在Spring Boot中集成Apache Shiro可以为应用程序提供授权认证、会话加密、会话管理等功能。下面我们就来详细介绍一下如何在Spring Boot集成Apache Shiro。

环境准备

引入依赖

首先,我们需要在在pom.xml中添加Apache Shiro相关依赖,如下所示。

<dependency>
    <groupId>org.apache.shiro</groupId>
    <artifactId>shiro-spring</artifactId>
    <version>1.9.1</version>
</dependency>

具体实现

在Apache Shiro提供了Realm、SecurityManager、ShiroFilter等组件,如下所示。

  • Realm:定义认证和授权的规则。
  • SecurityManager:Shiro的核心,用于管理所有安全操作。
  • ShiroFilter:负责拦截请求并执行相应的认证和授权检查。

接下来我们就分别配置这些组件来实现Apache Shiro安全认证。

配置Realm

Realm是用于在Apache Shiro中连接数据源并进行用户认证与授权类。所以,这里我们可以创建一个自定义Realm类,假设在数据库中存储了用户信息,如下所示。

public class MyRealm extends AuthorizingRealm {

    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
        // 假设添加一些角色和权限(实际可从数据库加载)
        authorizationInfo.addRole("admin");
        authorizationInfo.addStringPermission("user:read");
        return authorizationInfo;
    }

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        UsernamePasswordToken upToken = (UsernamePasswordToken) token;
        String username = upToken.getUsername();

        // 假设从数据库查找用户信息
        if ("user".equals(username)) {
            return new SimpleAuthenticationInfo(username, "password123", getName());
        } else {
            throw new AuthenticationException("用户不存在");
        }
    }
}

在这个自定义的Realm中,我们可以通过doGetAuthenticationInfo方法来实现用户的认证操作,通过doGetAuthorizationInfo方法用来进行用户的授权操作。

配置SecurityManager

定义完成之后,我们需要配置安全管理器,在ShiroConfig配置类中配置SecurityManager和Realm,如下所示。

@Configuration
public class ShiroConfig {

    @Bean
    public MyRealm myRealm() {
        return new MyRealm();
    }

    @Bean
    public SecurityManager securityManager(MyRealm myRealm) {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        securityManager.setRealm(myRealm);
        return securityManager;
    }

    @Bean
    public ShiroFilterFactoryBean shiroFilter(SecurityManager securityManager) {
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        shiroFilterFactoryBean.setSecurityManager(securityManager);

        // 配置拦截规则
        Map<String, String> filterMap = new HashMap<>();
        filterMap.put("/login", "anon"); // 允许匿名访问
        filterMap.put("/logout", "logout");
        filterMap.put("/**", "authc"); // 其他请求需要认证

        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterMap);

        // 配置登录和未授权跳转的页面
        shiroFilterFactoryBean.setLoginUrl("/login");
        shiroFilterFactoryBean.setUnauthorizedUrl("/unauthorized");

        return shiroFilterFactoryBean;
    }
}

在这个配置中,我们配置了ShiroFilterFactoryBean的过滤规则,用来指定哪些路径需要授权认证,哪些路径不需要进行授权认证,而loginUrl和unauthorizedUrl用于定义默认的登录和未授权页面。

配置会话管理

在分布式系统中Shiro还提供了会话管理功能,我们可以通过在ShiroConfig中配置SessionManager来支持自定义的会话管理操作。如下所示。

import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.apache.shiro.session.mgt.SessionManager;

@Bean
public SessionManager sessionManager() {
    DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();
    sessionManager.setGlobalSessionTimeout(1800000); // 设置会话超时时间(单位:毫秒)
    return sessionManager;
}

创建登录测试接口

配置完成之后,我们就可以创建一个简单的登录接口类,用来测试通过Shiro进行用户授权等操作。如下所示。

@RestController
public class LoginController {

    @PostMapping("/login")
    public String login(@RequestParam("username") String username, 
                        @RequestParam("password") String password) {
        Subject subject = SecurityUtils.getSubject();
        UsernamePasswordToken token = new UsernamePasswordToken(username, password);

        try {
            subject.login(token);
            return "登录成功";
        } catch (Exception e) {
            return "登录失败:" + e.getMessage();
        }
    }

    @GetMapping("/logout")
    public String logout() {
        SecurityUtils.getSubject().logout();
        return "已登出";
    }
}

在这个Controller中,定义了两个端点,其中/login会获取用户提交的用户名和密码,并尝试通过Shiro进行认证,而/logout则是用来退出登录的调用端点。

总结

通过上面的实现操作,我们就可以实现Shiro安全框架与Spring Boot的整合,在实际的使用场景中,我们可以对其进行进一步的优化升级,例如可以进一步配置缓存、密码加密、权限动态加载等,来构建一个更完整的安全体系。有兴趣的读者可以基于以上的项目对其进行扩展。相关问题我们可以在评论区讨论。

点击这里复制本文地址 以上内容由nimo97整理呈现,请务必在转载分享时注明本文地址!如对内容有疑问,请联系我们,谢谢!
qrcode

尼墨宝库 © All Rights Reserved.  蜀ICP备2024111239号-7