SpringBoot整合Shiro实现用户认证

简介: SpringBoot整合Shiro实现用户认证

前言

大家好,一直以来我都本着用最通俗的话理解核心的知识点, 我认为所有的难点都离不开 基础知识 的铺垫。目前正在出一个SpringBoot长期系列教程,从入门到进阶, 篇幅会较多~


适合人群

  • 学完Java基础
  • 想通过Java快速构建web应用程序
  • 想学习或了解SpringBoot
  • SpringBoot进阶学习

大佬可以绕过 ~


背景

如果你是一路看过来的,很高兴你能够耐心看完。之前带大家学了Springboot基础部分,对基本的使用有了初步的认识, 接下来的几期内容将会带大家进阶使用,会先讲解基础中间件的使用和一些场景的应用,或许这些技术你听说过,没看过也没关系,我会带大家一步一步的入门,耐心看完你一定会有收获~


情景回顾

上期带大家学习了Shiro安全框架的基本概念和工作原理, 相信有了基本的认识之后,下面学习将会容易些,本期将带大家学习整合Shiro框架和基本使用。同样的,我们集成到Springboot中。


项目源码(持续更新 欢迎star⭐️)


环境搭建

我们先修改pom.xml, 引入相关依赖, 为了后期方便学习,我对项目结构做了一些调整,在目录下新建一个模块用于Shiro学习, 具体大家可以查看源码:

<!-- shiro-spring -->
<dependency>
    <groupId>org.apache.shiro</groupId>
    <artifactId>shiro-spring</artifactId>
    <version>1.4.0</version>
</dependency>
复制代码


配置 Shiro

今天带大家实现一个用户认证的功能, 我们先添加配置ShiroConfig:

@Configuration
public class ShiroConfig {
    @Bean
    public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager) {
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        // 设置securityManager
        shiroFilterFactoryBean.setSecurityManager((SecurityManager) securityManager);
        // 登录的url
        shiroFilterFactoryBean.setLoginUrl("/login");
        // 登录成功后跳转的url
        shiroFilterFactoryBean.setSuccessUrl("/index");
        // 未授权url
        shiroFilterFactoryBean.setUnauthorizedUrl("/403");
        LinkedHashMap<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
        // 定义filterChain,静态资源不拦截
        filterChainDefinitionMap.put("/css/**", "anon");
        filterChainDefinitionMap.put("/js/**", "anon");
        filterChainDefinitionMap.put("/fonts/**", "anon");
        filterChainDefinitionMap.put("/img/**", "anon");
        // druid数据源监控页面不拦截
        filterChainDefinitionMap.put("/druid/**", "anon");
        // 配置退出过滤器,其中具体的退出代码Shiro已经替我们实现了
        filterChainDefinitionMap.put("/logout", "logout");
        filterChainDefinitionMap.put("/", "anon");
        // 除上以外所有url都必须认证通过才可以访问,未通过认证自动访问LoginUrl
        filterChainDefinitionMap.put("/**", "authc");
        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
        return shiroFilterFactoryBean;
    }
    @Bean
    public DefaultWebSecurityManager securityManager(){
        // 配置SecurityManager,并注入shiroRealm
        DefaultWebSecurityManager securityManager =  new DefaultWebSecurityManager();
        securityManager.setRealm(shiroRealm());
        return securityManager;
    }
    /**
     * 自定义实现的Realm
     * @return
     */
    @Bean
    public CustomRealm shiroRealm(){
        CustomRealm shiroRealm = new CustomRealm();
        return shiroRealm;
    }
}
复制代码


简单说下, anon代表的是允许资源公开访问, authc代表的是资源需要通过认证后才能访问。其实大部分都已经贴在注释上了,大家跟着配就好,重点关注的是shiroRealm()这个方法, 里边有一个类需要我们自行实现,下边我就带大家实现一下:

public class CustomRealm extends AuthorizingRealm {
    /**
     * 获取用户角色和权限
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principal) {
        return null;
    }
    /**
     * 登录认证
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        // 获取用户输入的用户名和密码
        String userName = (String) token.getPrincipal();
        String password = new String((char[]) token.getCredentials());
        System.out.println("用户" + userName + "认证-----ShiroRealm.doGetAuthenticationInfo");
        // 通过用户名到数据库查询用户信息
        User user = UserMock.getUserByUsername(userName);
        if (user == null) {
            throw new UnknownAccountException("用户名或密码错误!");
        }
        if (!password.equals(user.getPassword())) {
            throw new IncorrectCredentialsException("用户名或密码错误!");
        }
        if (user.getState().equals("0")) {
            throw new LockedAccountException("账号已被锁定,请联系管理员!");
        }
        SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(user, password, getName());
        return info;
    }
}
复制代码


这里为了方便演示,我直接写死到对象里,使用测试数据来模拟数据库查询到的用户信息,真实业务中是要去数据库查询用户信息的:

@Data
public class User {
    public Integer id;
    public String username;
    public String password;
    public String role;
    public String state;
}
复制代码


定义一个 UserMock

public class UserMock {
    public static String getPassword(String username) {
        System.out.println("用户名:   " + username);
        if(username.equals("admin")) {
            return "123";
        }else {
            return "456";
        }
    }
    public static String getRole(String username) {
        if(username.equals("admin")) {
            return "admin";
        }else {
            return "user";
        }
    }
    public static User getUserByUsername(String username) {
        User user = new User();
        if(username.equals("admin")) {
            user.setUsername("admin");
            user.setPassword("123");
            user.setRole("admin");
        }else {
            user.setUsername("admin1");
            user.setPassword("456");
            user.setRole("user");
        }
        user.setState("1");
        return user;
    }
}
复制代码


定义一个首页控制器:

@RestController
public class IndexController {
    @RequestMapping("/index")
    public String index(Model model) {
        // 登录成后,即可通过Subject获取登录的用户信息
        User user = (User) SecurityUtils.getSubject().getPrincipal();
        model.addAttribute("user", user);
        return "index";
    }
}
复制代码


定义一个登录控制器:

@RestController
public class LoginController {
    @GetMapping("/login")
    public String login() {
        return "login";
    }
    @PostMapping("/login")
    @ResponseBody
    public String login(String username, String password) {
        UsernamePasswordToken token = new UsernamePasswordToken(username, password);
        // 获取Subject对象
        Subject subject = SecurityUtils.getSubject();
        try {
            // 执行登录
            subject.login(token);
            return "ok";
        } catch (UnknownAccountException e) {
            return e.getMessage();
        } catch (IncorrectCredentialsException e) {
            return "IncorrectCredentialsException " + e.getMessage();
        } catch (LockedAccountException e) {
            return "LockedAccountException " + e.getMessage();
        } catch (AuthenticationException e) {
            return "认证失败!";
        }
    }
}
复制代码


运行项目,访问: http://localhost:8878/api/index,  发现没法直接访问自动跳转到了http://localhost:8878/api/login;jsessionid=F7E2EABECB7D87B89EA99C328B344B05,说明我们还未登录, 下面进行登录 POST http://localhost:8878/api/login, 登录成功后会自动跳转/index, 并且返回结果 index --->admin, 说明我们之前的配置都生效了,并且可以通过Subject拿到用户信息


结束语

本期内容就到这里结束了, 总结一下主要讲了在SpringBoot中如何集成Shiro,以及带大家学习了它的基本配置,最后我们完成了一个用户认证的功能。


下期预告

细心的同学可能会发现,当我们浏览器关闭在进来访问首页index的时候,发现又跳转回了登录,这样的交互肯定是不友好的,所以下期带大家学习如何在Shiro中存储我们的Cookie,让它记住我们的信息

相关文章
|
2月前
|
安全 Java Apache
SpringBoot+Shiro(一)
SpringBoot+Shiro(一)
|
1月前
|
安全 Java 数据库
shiro学习一:了解shiro,学习执行shiro的流程。使用springboot的测试模块学习shiro单应用(demo 6个)
这篇文章是关于Apache Shiro权限管理框架的详细学习指南,涵盖了Shiro的基本概念、认证与授权流程,并通过Spring Boot测试模块演示了Shiro在单应用环境下的使用,包括与IniRealm、JdbcRealm的集成以及自定义Realm的实现。
42 3
shiro学习一:了解shiro,学习执行shiro的流程。使用springboot的测试模块学习shiro单应用(demo 6个)
|
1月前
|
Java API Apache
Springboot+shiro,完整教程,带你学会shiro
这篇文章提供了一个完整的Apache Shiro与Spring Boot结合使用的教程,包括Shiro的配置、使用以及在非Web和Web环境中进行身份验证和授权的示例。
65 2
Springboot+shiro,完整教程,带你学会shiro
|
1月前
|
前端开发 Java Apache
Springboot整合shiro,带你学会shiro,入门级别教程,由浅入深,完整代码案例,各位项目想加这个模块的人也可以看这个,又或者不会mybatis-plus的也可以看这个
本文详细讲解了如何整合Apache Shiro与Spring Boot项目,包括数据库准备、项目配置、实体类、Mapper、Service、Controller的创建和配置,以及Shiro的配置和使用。
292 1
Springboot整合shiro,带你学会shiro,入门级别教程,由浅入深,完整代码案例,各位项目想加这个模块的人也可以看这个,又或者不会mybatis-plus的也可以看这个
|
1月前
|
NoSQL Java Redis
shiro学习四:使用springboot整合shiro,正常的企业级后端开发shiro认证鉴权流程。使用redis做token的过滤。md5做密码的加密。
这篇文章介绍了如何使用Spring Boot整合Apache Shiro框架进行后端开发,包括认证和授权流程,并使用Redis存储Token以及MD5加密用户密码。
29 0
shiro学习四:使用springboot整合shiro,正常的企业级后端开发shiro认证鉴权流程。使用redis做token的过滤。md5做密码的加密。
|
14天前
|
JavaScript NoSQL Java
CC-ADMIN后台简介一个基于 Spring Boot 2.1.3 、SpringBootMybatis plus、JWT、Shiro、Redis、Vue quasar 的前后端分离的后台管理系统
CC-ADMIN后台简介一个基于 Spring Boot 2.1.3 、SpringBootMybatis plus、JWT、Shiro、Redis、Vue quasar 的前后端分离的后台管理系统
29 0
|
3月前
|
SQL Java 数据库连接
springboot+mybatis+shiro项目中使用shiro实现登录用户的权限验证。权限表、角色表、用户表。从不同的表中收集用户的权限、
这篇文章介绍了在Spring Boot + MyBatis + Shiro项目中,如何使用Shiro框架实现登录用户的权限验证,包括用户、角色和权限表的设计,以及通过多个表查询来收集和验证用户权限的方法和代码实现。
springboot+mybatis+shiro项目中使用shiro实现登录用户的权限验证。权限表、角色表、用户表。从不同的表中收集用户的权限、
|
3月前
|
SQL 前端开发 Java
springboot项目中使用shiro实现用户登录以及权限的验证
这篇文章详细介绍了如何在Spring Boot项目中集成Apache Shiro框架来实现用户登录和权限验证,包括项目依赖配置、数据库连接、实体类定义、控制器、服务层、Mapper层以及前端页面的实现,并展示了实际效果和过滤器代码。
springboot项目中使用shiro实现用户登录以及权限的验证
|
3月前
|
NoSQL 安全 Java
Java Spring Boot中使用Shiro、JWT和Redis实现用户登录鉴权
Java Spring Boot中使用Shiro、JWT和Redis实现用户登录鉴权
|
3月前
|
JSON 前端开发 Java
Spring Boot JWT 用户认证
Spring Boot JWT 用户认证
17 0