sprintboot集成Shiro的基本使用

目录

1,前言

2, Shiro的介绍

3,Shiro功能

 4,基本使用

4.1 引入一个依赖

4.2 配置两个Bean

4.3 实现两个方法

 4.4 权限控制

4.4.1 AdvisorAutoProxyCreator

4.4.2 AuthorizationAttributeSourceAdvisor

5,源码参考

5.1 Gittee


1,前言

在以往的权限管理中,我们的权限管理通常是有以下几个步骤:
        1.创建用户,分配权限。
        2.用户登录,权限拦截器拦截请求,识别当前用户登录信息
        3.从权限表中判断是否拥有权限


 从以上步骤中可以提取到以下三个问题。

1.如何让Shiro拦截请求。
        在web开发中,Shiro会提供一个拦截器来对请求进行拦截。

2.Shiro如何判断发起请求用户的身份?
        在web开发中,会借助session来判断,如果禁用了session,那么可能需要重写一些方法。

3.如何判断权限?
        Shiro使用realm来判断权限。

2, Shiro的介绍

  • Apache Shiro是一个强大且易用的Java安全框架,执行身份验证、授权、密码和会话管理。使用Shiro的易于理解的API,您可以快速、轻松地获得任何应用程序,从最小的移动应用程序到最大的网络和企业应用程序。
  • Shiro不仅可以用于javaEE环境,也可以用于javaSE

3,Shiro功能

  • Authentication:身份认证,验证用户是否拥有某个身份。
  • Authorization: 权限校验,验证某个已认证的用户是否拥有某个权限。确定“谁”可以访问“什么”。
  • Session Management:会话管理,管理用户登录后的会话,
  • Cryptography:加密,使用密码学加密数据,如加密密码。
  • Web Support:Web支持,能够比较轻易地整合到Web环境中。
  • Caching:缓存,对用户的数据进行缓存,
  • Concurrency:并发,Apache Shiro支持具有并发功能的多线程应用程序,也就是说支持在多线程应用中并发验证。
  • Testing:测试,提供了测试的支持。
  • Run as :允许用户以其他用户的身份来登录。
  • Remember me :记住我

4,基本使用

4.1 引入一个依赖

新建一个基于Springboot的Web项目,引入Shiro依赖。

 <!-- https://mvnrepository.com/artifact/org.apache.shiro/shiro-web -->
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-spring</artifactId>
            <version>1.4.0</version>
        </dependency>

4.2 配置两个Bean

    新建一个shiroConfig配置类,配置Shiro最为核心的安全管理器SecurityManager。这里准确来说配置了三个Bean,形参中的UserAuthorizingRealm是通过@Component扫描进去的,不添加这个注解直接配置在ShiroConfig中也行。

    /**
     * 配置安全管理器,Shiro最核心的组件
     *
     * @param userRealm
     * @return
     */
    @Bean
    public SecurityManager securityManager(UserAuthorizingRealm userRealm) {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        securityManager.setRealm(userRealm);
        // 取消Cookie中的RememberMe参数
        securityManager.setRememberMeManager(null);
        // 配置自定义Session管理器
//        securityManager.setSessionManager(mySessionManager());
        return securityManager;
    }

再配置Shiro的过滤器工厂类,将上一步配置的安全管理器注入,并配置相应的过滤规则。

    //* authc:配置的url都必须认证通过才可以访问,它是Shiro内置的一个过滤器
    //* 对应的实现类 @see org.apache.shiro.web.filter.authc.FormAuthenticationFilter
    //
    //* anon:也是Shiro内置的,它对应的过滤器里面是空的,什么都没做,可以理解为不拦截
    //* 对应的实现类 @see org.apache.shiro.web.filter.authc.AnonymousFilter
    @Bean
    public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager) {
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        shiroFilterFactoryBean.setSecurityManager(securityManager);
        // 登录页面,无权限时跳转的路径
        shiroFilterFactoryBean.setLoginUrl("/login");
        // 配置拦截规则
        Map<String, String> filterMap = new LinkedHashMap<>();
        // 首页配置放行
        filterMap.put("/", "anon");
        // 登录页面和登录请求路径需要放行
        filterMap.put("/login", "anon");
        filterMap.put("/do_login", "anon");
        // 其他未配置的所有路径都需要通过验证,否则跳转到登录页
        filterMap.put("/**", "authc");
        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterMap);
        return shiroFilterFactoryBean;
    }

      上面使用LinkedHashMap是为了保持顺序,Filter的配置顺序不能随便打乱,过滤器是按照我们配置的顺序来匹配的。范围大的过滤器要放在后面,/**这条如果放在前面,那么一来就匹配上了,就不会继续再往后走了。

4.3 实现两个方法

在上一步的安全管理器配置中,我们通过形参注入了一个UserAuthorizingRealm对象,这个就是认证和授权相关的流程,需要我们自己实现。继承AuthorizingRealm之后,我们需要实现两个抽象方法,一个是认证,一个是授权,这两个方法长得很像,别弄混淆了。

doGetAuthenticationInfo认证。相当于登录,只有通过登录了,才能进行后面授权的操作。一些只需要登录权限的操作,在登录成功后就可以访问了,比如上一步中配置的authc过滤器就是只需要登录权限的。

doGetAuthorizationInfo授权。认证过后,仅仅拥有登录权限,更多细粒度的权限控制,比如菜单权限,按钮权限,甚至方法调用权限等,都可以通过授权轻松实现。在这个方法里,我们可以拿到当前登录的用户,再根据实际业务赋予用户部分或全部权限,当然这里也可以赋予用户某些角色,后面也可以根据角色鉴权。下方的演示代码仅添加了权限,赋予角色可以调用addRoles()或者setRoles()方法,传入角色集合。

package com.example.shirodemo.shiro;

import com.example.shirodemo.entity.User;
import com.example.shirodemo.service.LoginService;
import org.apache.shiro.SecurityUtils;
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 org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.*;

/**
 * UserRealm,实现认证和授权
 *
 * @author woqing
 */
@Component
public class UserAuthorizingRealm extends AuthorizingRealm {

    @Autowired
    private LoginService loginService;

    /**
     * 授权验证,获取授权信息
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        User user = (User) principalCollection.getPrimaryPrincipal();
        List<String> perms;
        // 系统管理员拥有最高权限
        if (User.SUPER_ADMIN == user.getId()) {
            perms = loginService.getAllPerms();
        } else {
            perms = loginService.getUserPerms(user.getId());
        }

        // 权限Set集合
        Set<String> permsSet = new HashSet<>();
        for (String perm : perms) {
            permsSet.addAll(Arrays.asList(perm.trim().split(",")));
        }

        // 返回权限
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        info.setStringPermissions(permsSet);
        return info;
    }

    /**
     * 登录验证,获取身份信息
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;
        // 获取用户
        User user = loginService.getUserByUsername(token.getUsername());
        if (user == null) {
            throw new UnknownAccountException("账号或密码不正确");
        }
        // 判断用户是否被锁定
        if (user.getStatus() == null || user.getStatus() == 1) {
            throw new LockedAccountException("账号已被锁定,请联系管理员");
        }
        // 验证密码
        if (!user.getPassword().equals(new String(token.getPassword()))) {
            throw new UnknownAccountException("账号或密码不正确");
        }
        user.setSessionId(SecurityUtils.getSubject().getSession().getId().toString());
        // 设置最后登录时间
        user.setLastLoginTime(new Date());
        // 此处可以持久化用户的登录信息,这里仅做演示没有连接数据库
        return new SimpleAuthenticationInfo(user, user.getPassword(), getName());
    }
}

这样配置完成以后,就可以基于URL做复杂的权限控制了,我们可以通过不同的过滤器为URL配置不同的权限。

Shiro提供了很多内置的过滤器,我们最常用的就是第一个和第二个。如果对其效果不满意,我们还可以自定义过滤器实现权限控制。

 4.4 权限控制

4.4.1 AdvisorAutoProxyCreator

        注解式的权限控制需要配置两个Bean,第一个是AdvisorAutoProxyCreator,代理生成器,需要借助SpringAOP来扫描@RequiresRoles和@RequiresPermissions等注解,生成代理类实现功能增强,从而实现权限控制。需要配合AuthorizationAttributeSourceAdvisor一起使用,否则权限注解无效。

    /**
     * 代理生成器,需要借助SpringAOP来扫描@RequiresRoles和@RequiresPermissions等注解。
     * 生成代理类实现功能增强,从而实现权限控制。
     * 需要配合AuthorizationAttributeSourceAdvisor一起使用,否则权限注解无效。
     */
    @Bean
    public DefaultAdvisorAutoProxyCreator lifecycleBeanPostProcessor() {
        DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
        // 这里需要设置为True,否则 @RequiresPermissions 注解验证不生效
        advisorAutoProxyCreator.setProxyTargetClass(true);
        return advisorAutoProxyCreator;
    }

4.4.2 AuthorizationAttributeSourceAdvisor

        上面配置的DefaultAdvisorAutoProxyCreator相当于一个切面,下面这个类就相当于切点了,两个一起才能实现注解权限控制。

    /**
     * 上面配置的DefaultAdvisorAutoProxyCreator相当于一个切面,下面这个类就相当于切点了,两个一起才能实现注解权限控制。
     */
    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
        AuthorizationAttributeSourceAdvisor advisor = new AuthorizationAttributeSourceAdvisor();
        advisor.setSecurityManager(securityManager);
        return advisor;
    }

        配置完上面两个Bean之后我们就可以使用注解来控制权限了,Shiro中的权限注解有很多,我们最常用的其实就两个,@RequiresRoles和@RequiresPermissions,前者是角色验证,后者是权限验证。他们都可以传入两个参数,value是必须的,可以传入一个字符数组,表示一个或多个角色(权限),另一个参数logical有两个值可选,AND和OR,默认为AND,表示这组角色(权限)是必须都有还是仅需要一个就能访问。

4.5 举个栗子:

 以上代码表示 info()方法需要当前登录用户拥有user:list或者user:list权限才能访问。

 更多shiro注解解析:shiro的@RequiresPermissions五种注解使用说明

5,源码参考

5.1 Gittee

Shiro(一):Shiro的基本使用

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
对于Spring Boot集成Shiro,你可以按照以下步骤进行操作: 1. 首先,在你的Spring Boot项目中添加Shiro的依赖。你可以在pom.xml文件中添加以下依赖关系: ```xml <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-spring-boot-starter</artifactId> <version>1.7.1</version> </dependency> ``` 2. 创建一个Shiro的配置类,用于配置Shiro的相关组件和属性。可以使用`@Configuration`注解来标记该类作为配置类,并使用`@EnableShiroAnnotation`注解来启用Shiro的注解支持。 ```java @Configuration @EnableShiroAnnotation public class ShiroConfig { // 配置Shiro的相关组件和属性 // ... } ``` 3. 在上述配置类中,可以配置Shiro的Realm、Session管理器、缓存管理器等组件。你可以根据自己的需求选择相应的实现类并进行配置。 ```java @Configuration @EnableShiroAnnotation public class ShiroConfig { @Bean public Realm realm() { // 配置自定义的Realm实现类 // ... return realm; } @Bean public SessionManager sessionManager() { // 配置自定义的Session管理器实现类 // ... return sessionManager; } @Bean public CacheManager cacheManager() { // 配置自定义的缓存管理器实现类 // ... return cacheManager; } // 其他配置项... } ``` 4. 在主配置类中,添加`@Import`注解来引入Shiro的配置类。 ```java @SpringBootApplication @Import(ShiroConfig.class) public class YourApplication { public static void main(String[] args) { SpringApplication.run(YourApplication.class, args); } } ``` 5. 在需要进行权限控制的地方,使用Shiro的注解来标记需要进行权限验证的方法或类。例如,可以使用`@RequiresRoles`注解来限制具有特定角色的用户才能访问方法。 ```java @RestController public class YourController { @RequiresRoles("admin") @GetMapping("/admin") public String admin() { return "Hello, admin!"; } } ``` 这样,你就成功地集成Spring Boot和Shiro,并可以进行基于角色的权限控制了。当然,以上只是一个简单的示例,你可以根据自己的需求进行更详细的配置和使用

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

superboy@.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值