您的位置:

Spring Boot集成Shiro实现权限管理

一、概述

Shiro是一个Java安全框架,提供了身份验证、授权、密码加密和会话管理等功能。可以集成到任何Java应用程序中,包括Web、REST API和大数据架构等。Spring Boot是一个使创建Spring应用程序更容易的框架,提供了自动配置和约定大于配置的方式。集成Shiro和Spring Boot可以快速实现安全和权限管理。

二、集成Shiro

在Spring Boot中集成Shiro有多种方式,可以手动配置,也可以使用starter快速集成。下面以使用starter为例,介绍如何集成。

1. 添加依赖


<dependency>
    <groupId>org.apache.shiro</groupId>
    <artifactId>shiro-spring-boot-starter</artifactId>
    <version>1.7.1</version>
</dependency>

2. 配置Shiro

在application.properties中添加Shiro的配置:


shiro:
  loginUrl: /login
  successUrl: /index
  unauthorizedUrl: /403
  # 自定义ShiroFilterFactoryBean
  filters:
    myFilter: cn.example.MyFilter
  filterChainDefinitions: 
    # 匿名访问
    /anonymous/** = anon
    # 记住我功能
    /rememberMe/** = user
    # 登录页面和登录请求
    /login/** = anon
    # 其他请求需要认证
    /** = myFilter

其中,loginUrl、successUrl和unauthorizedUrl分别表示登录页面、登录成功后跳转的页面和没有权限时访问的页面。filterChainDefinitions指定请求的过滤器。

3. 配置SecurityManager

在配置类中添加SecurityManager:


@Bean
public SecurityManager securityManager() {
    DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
    securityManager.setRealm(myRealm()); // 设置Realm
    securityManager.setSessionManager(sessionManager()); // 设置SessionManager
    return securityManager;
}

4. 配置Realm

自定义Realm需要继承org.apache.shiro.realm.AuthorizingRealm类,并实现doGetAuthenticationInfo和doGetAuthorizationInfo方法:


public class MyRealm extends AuthorizingRealm {

    // 授权
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        // 获取当前用户
        String username = (String) principals.getPrimaryPrincipal();
        // 根据用户名从数据库中获取角色和权限信息
        Set<String> roles = userDao.findRoles(username);
        Set<String> permissions = userDao.findPermissions(username);
        // 将角色和权限信息封装到AuthorizationInfo中
        SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
        authorizationInfo.setRoles(roles);
        authorizationInfo.setStringPermissions(permissions);
        return authorizationInfo;
    }

    // 认证
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        String username = (String) token.getPrincipal();
        User user = userDao.findByUsername(username);
        if (user == null) {
            throw new UnknownAccountException("账户不存在");
        }
        SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(username, user.getPassword(), getName());
        return authenticationInfo;
    }
}

5. 配置SessionManager

在SecurityManager中必须配置SessionManager,Spring Boot中可以使用org.apache.shiro.session.mgt.ExecutorServiceSessionValidationScheduler类实现会话管理:


@Bean
public SessionManager sessionManager() {
    ServletContainerSessionManager sessionManager = new ServletContainerSessionManager();
    sessionManager.setSessionValidationSchedulerEnabled(true); // 开启会话调度
    sessionManager.setSessionValidationScheduler(getSessionValidationScheduler()); // 设置会话调度器
    sessionManager.setGlobalSessionTimeout(3600000); // 设置会话过期时间
    sessionManager.setSessionIdCookieEnabled(true); // 允许客户端携带Session ID Cookie
    return sessionManager;
}

private ExecutorServiceSessionValidationScheduler getSessionValidationScheduler() {
    ExecutorServiceSessionValidationScheduler scheduler = new ExecutorServiceSessionValidationScheduler();
    scheduler.setInterval(1800000); // 设置会话验证间隔为30分钟
    scheduler.setSessionFactory(((DefaultSessionManager) securityManager().getSessionManager()).getSessionFactory());
    return scheduler;
}

三、实现权限管理

1. 基于注解的权限控制

可以使用@RequiresPermissions注解实现对方法或类的访问控制,如下所示:


@RequiresPermissions("user:list")
@RequestMapping("/list")
public String list() {
    return "user/list";
}

在上述代码中,如果当前用户没有user:list这个权限,则无法访问/list路径。

2. 基于URL的权限控制

可以使用filterChainDefinitions属性配置URL的访问控制规则,如下所示:


filterChainDefinitions: 
    # 匿名访问
    /anonymous/** = anon
    # 记住我功能
    /rememberMe/** = user
    # 登录页面和登录请求
    /login/** = anon
    # 其他请求需要认证
    /** = myFilter

在上述代码中,/anonymous路径可以匿名访问,/rememberMe路径需要经过认证,/login路径可以匿名访问,其他路径需要经过自定义的过滤器myFilter处理。

3. 实现Remember Me功能

使用Shiro可以实现Remember Me功能,下面是相关代码:


@Bean
public RememberMeManager rememberMeManager() {
    CookieRememberMeManager rememberMeManager = new CookieRememberMeManager();
    rememberMeManager.setCookie(simpleCookie());
    return rememberMeManager;
}

@Bean
public SimpleCookie simpleCookie() {
    SimpleCookie cookie = new SimpleCookie("rememberMe");
    cookie.setMaxAge(604800); // 设置Cookie过期时间为7天
    return cookie;
}

在上述代码中,设置Cookie的过期时间并注入到RememberMeManager中即可实现Remember Me功能。在登录页面简单设置一下记住我即可启用这个功能。

4. 实现Session管理

在SecurityManager中配置SessionManager即可实现Session管理。具体实现可以参考上述代码中的sessionManager方法和getSessionValidationScheduler方法。

四、总结

通过本文的介绍,我们可以了解到Spring Boot集成Shiro的方法和实现权限管理的方式。Shiro提供了身份验证、授权、密码加密和会话管理等功能,可以很好地处理安全和权限相关的问题。在使用Shiro时,我们可以结合自己的应用场景来选择使用基于注解的权限控制或基于URL的访问控制。同时,通过Remember Me和Session管理功能可以更好地保护用户的安全和隐私。