【Shiro】SpringBoot集成Shiro权限认证《上》

基础认识

Subject

主体,代表了当前的“用户”,这个用户不一定是一个具体的人,与当前应用交互的任何东西都是主体,如第三方进程、网络爬虫、机器人等,Subject是一个抽象概念,所有的Subject都绑定到SecurityManager,与Subject的所有交互都会委托给SecurityManager,可以把Subject认为是一个门面;SecurityManager才是实际的执行者.

SecurityManager

安全管理器,即所有与安全有关的操作都会与SecurityManager进行交互,是Shiro框架的核心,
管理所有的Subject,类似于Spring MVC的前端控制器DispatcherServlet;

Realms

Shiro从Realm中获取安全数据(比如用户、角色、权限),SecurityManager要验证用户身份,
需要从Realm中获取相应的用户进行比较确定用户是否合法;验证用户角色/权限也需要从Realm获得相应数据进行比较,类似于DataSource,安全数据源;它封装了数据源的连接细节,并在需要时将相关数据提供给Shiro。

总之:

用户、权限是通过Realm让开发人员自己注入到SecurityManager,从而让SecurityManager能得到合法的用户以及权限进行判断;

开始

创建SpringBoot项目

依赖引入


    <dependency>
        <groupId>org.apache.shirogroupId>
        <artifactId>shiro-spring-boot-starterartifactId>
        <version>1.5.3version>
    dependency>
    <dependency>
        <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-starter-webartifactId>
    dependency>
    <dependency>
        <groupId>org.projectlombokgroupId>
        <artifactId>lombokartifactId>
        <optional>trueoptional>
    dependency>
    
    <dependency>
        <groupId>org.apache.shirogroupId>
        <artifactId>shiro-spring-boot-starterartifactId>
        <version>1.5.3version>
    dependency>

自定义Realm

public class CustomerRealm extends AuthorizingRealm {

    /**
     * 授权逻辑
     * @param principalCollection
     * @return
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        System.out.println("执行了=>授权逻辑PrincipalCollection");
        return null;
    }

    /**
     * 认证逻辑
     * @param authenticationToken
     * @return
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) {
        System.out.println("执行了=>认证逻辑AuthenticationToken");
        return null;
    }
}

Shiro配置

  • 创建 ShiroFilterFactoryBean
  • 创建 DefaultWebSecurityManager
  • 创建 realm 对象

基础结构

@Configuration
public class ShiroConfig {
    
    /**
     * realm对象
     * @return
     */
    @Bean
    public CustomerRealm myShiroRealm() {
        return null;
    }

    /**
     * 权限管理,配置主要是Realm的管理认证
     * @return
     */
    @Bean
    public DefaultWebSecurityManager securityManager() {
       return null;
    }

    /**
     * Filter工厂,设置对应的过滤条件和跳转条件
     * @param securityManager
     * @return
     */
    @Bean
    public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager) {
        return null;
    }
}

创建Realm 对象

Realm对象

   /**
     * Realm对象
     * @return
     */
    @Bean
    public CustomerRealm myShiroRealm() {
        return new CustomerRealm();
    }

创建DefaultWebSecurityManager

权限管理,配置主要是Realm的管理认证

 /**
     * 权限管理,配置主要是Realm的管理认证
     * @return
     */
    @Bean
    public DefaultWebSecurityManager securityManager() {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        securityManager.setRealm(myShiroRealm());
        return securityManager;
    }

创建 ShiroFilterFactoryBean

Filter工厂,设置对应的过滤条件和跳转条件

   /**
     * Filter工厂,设置对应的过滤条件和跳转条件
     * @param securityManager
     * @return
     */
    @Bean
    public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager) {
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        //设置安全管理器
        shiroFilterFactoryBean.setSecurityManager(securityManager);
        return shiroFilterFactoryBean;
    }

登录接口

创建一个文件夹controller/LoginController.java

@RestController
public class LoginController {
    
    @GetMapping("/login")
    public String login(String userName,String passWord) {
        if (StringUtils.isEmpty(userName) || StringUtils.isEmpty(passWord)) {
            return "用户名密码不能为空";
        }
        //用户认证信息
        Subject subject = SecurityUtils.getSubject();
        UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken(userName, passWord);
        try {
            subject.login(usernamePasswordToken);
        } catch (UnknownAccountException e) {
            return "用户不存在";
        } catch (AuthenticationException e) {
            return "用户名密码错误";
        } catch (AuthorizationException e) {
            return "无权限登录";
        }
        return "登录成功";
    }
}

修改过滤条件以及认证逻辑

过滤条件

修改ShiroConfig中的过滤工厂,设置所有的请求都需要认证,放行登录请求。

注意:

这里有一些shiro内置的过滤请求,如下所示:

  • anon:无需认证就可以访问
  • authc:必须认证才可以访问
  • user:必须有“记住我”功能才能使用
  • perms:拥有对某个资源的权限才能访问
  • role:拥有某个角色权限才能访问
/**
     * Filter工厂,设置对应的过滤条件和跳转条件
     *
     * @param securityManager
     * @return
     */
    @Bean
    public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager) {
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        //设置安全管理器
        shiroFilterFactoryBean.setSecurityManager(securityManager);
        Map<String, String> map = new HashMap<>();
        //对所有用户认证
        map.put("/**", "authc");
        //登录
        shiroFilterFactoryBean.setLoginUrl("/login");
        shiroFilterFactoryBean.setFilterChainDefinitionMap(map);
        return shiroFilterFactoryBean;
    }

认证逻辑

shiro会自动帮我们去比对用户名和密码

在这里,定义了userName 和 passWord ,后续连接数据库后,这里应该是需要通过查询数据库。

 protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) {
        System.out.println("执行了=>认证逻辑AuthenticationToken");
        String userName = "admin";
        String passWord = "123456";
        //这里验证authenticationToken和simpleAuthenticationInfo的信息
     
        return  new SimpleAuthenticationInfo(userName, passWord, getName());
    }

到这里,我们可以启动我们工程,访问登录接口,测试一番了。

访问地址:http://localhost:8080/login -> 用户名密码不能为空
访问地址:http://localhost:8080/login?userName=wang&passWord=111 -> 用户名密码错误
访问地址: http://localhost:8080/login?userName=admin&passWord=123456 -> 登录成功

到这里,暂时结束了。下一章,会连接数据库,完成登录及权限认证相关操作。

你可能感兴趣的:(SpringBoot,spring,boot,后端,java)