shiro-与springboot集成

ragnar 1年前 ⋅ 199 阅读

本文将介绍shiro的springboot集成,基于官网的指南来做的。虽然比较简单,但还是注意一下版本的兼容性问题。

官网指南:https://shiro.apache.org/spring-boot.html

1 引入shiro

本demo使用springboot 2.2.6.RELEASE,shiro 则选择了 1.12.0。

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

PS:

shiro 的 1.12.0 版本可能无法支持 springboot 3.X 版本(比如:3.1.2)。
其一是因为新版本 AutoConfigurationExcludeFilter 中改成了对 @AutoConfiguration 注解扫描,导致无法正常自动配置。 从 shiro-spring-boot-web-starter 包的 spring.factory 文件中还是用的 EnableAutoConfiguration 注解来进行自动配置

2 提供一个Realm的实现

be like:

@Bean
public Realm realm(){
    SimpleAccountRealm accountRealm = new SimpleAccountRealm();
    accountRealm.addAccount("admin", "12345", ADMIN, USER);
    accountRealm.addAccount("user", "12345", USER);
    return accountRealm;
}

从上面这个简单的实现,不难看出 Realm 的实现类就是提供用来登录认证的账户信息的。
Realm 有多个实现类,可以挑选合适的,并继承它来做自定义的实现。 可以通过继承 AuthorizingRealm 类来做:

public class AccountRealm extends AuthorizingRealm {
    @Autowired
    private UserService userService;
    @Autowired
    private UserRoleService userRoleService;

    // 从基础数据存储中检索给定主体的授权信息。从此方法返回实例时,您可能需要考虑使用 SimpleAuthorizationInformation 的实例,因为它适用于大多数情况。
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        ...
    }

    // 从特定于实现的数据源(RDBMS、LDAP 等)中检索给定身份验证令牌的身份验证数据。
    // 对于大多数数据源,这意味着只需为关联的主体/用户“提取”身份验证数据,仅此而已,其余的让 Shiro 完成。但是在某些系统中,除了检索数据之外,这种方法实际上还可以执行特定于 EIS 的登录逻辑 - 这取决于 Realm 的实现。
    // null 返回值表示任何帐户都不能与指定的令牌关联。
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        ...
    }
}

3 提供一个 ShiroFilterChainDefinition

为了校验不同的请求路径要求的不同权限,需要用 ShiroFilterChainDefinition 类来定义好(映射)应用中任何特定的请求路径(path)的权限要求。

3.1 直接定义路径的角色&权限校验

@Bean
public ShiroFilterChainDefinition shiroFilterChainDefinition() {
    DefaultShiroFilterChainDefinition chainDefinition = new DefaultShiroFilterChainDefinition();

    // logged in users with the 'admin' role
    // 要求登录用户有 admin 角色的路径
    chainDefinition.addPathDefinition("/admin/**", "authc, roles[admin]");

    // logged in users with the 'document:read' permission
    // 要求登录用户有 document:read 这个权限的路径
    chainDefinition.addPathDefinition("/docs/**", "authc, perms[document:read]");

    // all other paths require a logged in user
    // 其它所有路径都要求用户要登录
    chainDefinition.addPathDefinition("/**", "authc");
    return chainDefinition;
}

3.2 通过 shiro 注解

@RequiresPermissions--权限要求注解

@RequiresPermissions("document:read")
public void readDocument() {
    ...
}

@RequiresRoles--角色要求注解:

@Controller
public class AccountInfoController {

    @RequiresRoles("admin")
    @RequestMapping("/admin/config")
    public String adminConfig(Model model) {
        return "view";
    }
}

@RequiresPermissions 和 @RequiresRoles 这两个注解即可以加在方法上面,也可以直接加到类上面。

此外,ShiroFilterChainDefinition 这个bean对象还是需要的:

@Bean
public ShiroFilterChainDefinition shiroFilterChainDefinition() {
    DefaultShiroFilterChainDefinition chainDefinition = new DefaultShiroFilterChainDefinition();
    chainDefinition.addPathDefinition("/**", "anon"); // all paths are managed via annotations【所有路径都通过注解进行管理】

    // or allow basic authentication, but NOT require it.【或允许基本身份验证,但不需要它】
    // chainDefinition.addPathDefinition("/**", "authcBasic[permissive]");
    return chainDefinition;
}

4 缓存管理器 CacheManager

需要启用自定义的缓存,那只需要提供一个缓存管理器的bean:

@Bean
protected CacheManager cacheManager() {
    return new MemoryConstrainedCacheManager();
}

如果要用 EhCache 或者 redis 等等,需要引用对应的 jar 包依赖,be like:

<dependency>
    <groupId>org.apache.shiro</groupId>
    <artifactId>shiro-ehcache</artifactId>
    <version>${shiro}</version>
</dependency>
@Bean
public CacheManager shiroCacheManager(net.sf.ehcache.CacheManager cacheManager) {
    EhCacheManager ehCacheManager = new EhCacheManager();
    ehCacheManager.setCacheManager(cacheManager);
    return ehCacheManager;
}

5 常见配置

KeyDefault ValueDescription
shiro.enabledtrue开启shiro的spring模块
shiro.web.enabledtrue开启shiro的spring web模块
shiro.annotations.enabledtrue开启spring支持shiro注解
shiro.userNativeSessionManagerfalse如果启用,Shiro将管理HTTP会话而不是容器
shiro.sessionManager.cookie.nameJSESSIONIDSession cookie 的名称
shiro.sessionManager.cookie.maxAge-1Session cookie 的最大年龄
shiro.rememberMeManager.cookie.namerememberMeRememberMe cookie 的名称
shiro.rememberMeManager.cookie.maxAgeone yearRememberMe cookie 的最大年龄
shiro.loginUrl/login.jsp登录页
shiro.successUrl/用户登录后的默认登录页面(如果在当前会话中找不到替代页面)
shiro.unauthorizedUrlnull如果用户未经授权,则重定向到的页面(403页面)

小结:

  1. 引入jar包依赖
  2. 提供一个Realm接口的实现--认证用的
  3. 提供 ShiroFilterChainDefinition 定义--对路径管控的定义
  4. 缓存管理器--用户登录信息的保存

springboot 3.x 自动配置类的扫描

与 spring.factories 的方式类似,需要在 META-INF 目录下创建 spring 目录,在里面创建一个文件名为: org.springframework.boot.autoconfigure.AutoConfiguration.imports

在文件内直接配置上要相关的配置类,be like:

org.apache.shiro.spring.boot.autoconfigure.ShiroBeanAutoConfiguration
org.apache.shiro.spring.boot.autoconfigure.ShiroAutoConfiguration
org.apache.shiro.spring.boot.autoconfigure.ShiroAnnotationProcessorAutoConfiguration

【由于shiro目前最新版本1.12.0并不支持springboot 3.x,所以自动配置这块还得自己来。此外,还是由于兼容性问题,最后我没有在项目中升级到shiro最新版本,而是继续使用目前的 1.4.0 版本(能平稳运行。。。)】


全部评论: 0

    我有话说:

    目录