Spring boot整合shiro+jwt实现前后端分离

下面是“Spring Boot整合Shiro+JWT实现前后端分离”的完整攻略,包含以下步骤:

1. 添加依赖

首先要在项目的pom.xml文件中添加相关依赖。

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

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

<dependency>
    <groupId>com.auth0</groupId>
    <artifactId>java-jwt</artifactId>
    <version>3.4.0</version>
</dependency>

2. 添加配置文件

在项目的application.yml配置文件中添加相应的配置。

# Shiro配置
shiro:
  filter:
    anon: /login, /api/doc, /static/**
    authc: /**
  jwt:
    secret: secret
    issuer: iss
    expiration: 1800

3. 编写Realm

编写自定义Realm类,并继承org.apache.shiro.realm.AuthorizingRealm类。

public class UserRealm extends AuthorizingRealm {

    @Autowired
    private UserService userService;

    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        return null;
    }

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        String username = (String) token.getPrincipal();
        User user = userService.findByUsername(username);
        if (user == null) {
            throw new UnknownAccountException();
        }
        return new SimpleAuthenticationInfo(user.getUsername(), user.getPassword(), getName());
    }
}

4. 配置ShiroFilterFactoryBean

@Bean
public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager) {
    ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
    shiroFilterFactoryBean.setSecurityManager(securityManager);
    Map<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
    filterChainDefinitionMap.put("/login", "anon");
    filterChainDefinitionMap.put("/api/doc", "anon");
    filterChainDefinitionMap.put("/static/**", "anon");
    filterChainDefinitionMap.put("/**", "jwt");
    shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
    return shiroFilterFactoryBean;
}

5. 配置ShiroSecurityManager

@Bean
public SecurityManager securityManager() {
    DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
    securityManager.setRealm(userRealm());
    securityManager.setSubjectFactory(servletContainerSubjectFactory());
    return securityManager;
}

@Bean
public UserRealm userRealm() {
    UserRealm userRealm = new UserRealm();
    userRealm.setCredentialsMatcher(hashedCredentialsMatcher());
    return userRealm;
}

@Bean
public ServletContainerSubjectFactory servletContainerSubjectFactory() {
    return new ServletContainerSubjectFactory();
}

@Bean
public HashedCredentialsMatcher hashedCredentialsMatcher() {
    HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
    hashedCredentialsMatcher.setHashAlgorithmName("SHA-256");
    hashedCredentialsMatcher.setHashIterations(1024);
    return hashedCredentialsMatcher;
}

6. 编写登录接口(示例1)

@PostMapping("/login")
public Result login(String username, String password) {
    UsernamePasswordToken token = new UsernamePasswordToken(username, password);
    try {
        SecurityUtils.getSubject().login(token);
    } catch (UnknownAccountException e) {
        return Result.error("用户名不存在");
    } catch (IncorrectCredentialsException e) {
        return Result.error("密码不正确");
    } catch (AuthenticationException e) {
        return Result.error("登录失败");
    }
    String jwt = JwtUtils.createJwt(username);
    Map<String, Object> data = new HashMap<>();
    data.put("token", jwt);
    return Result.ok("登录成功", data);
}

7. 编写JWT过滤器(示例2)

public class JwtFilter extends AuthenticatingFilter {

    @Override
    protected AuthenticationToken createToken(ServletRequest request, ServletResponse response) throws Exception {
        String jwt = JwtUtils.getJwtFromRequest((HttpServletRequest) request);
        return new JwtToken(jwt);
    }

    @Override
    protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
        HttpServletRequest req = (HttpServletRequest) request;
        HttpServletResponse resp = (HttpServletResponse) response;
        String jwt = JwtUtils.getJwtFromRequest(req);
        if (jwt == null) {
            resp.setStatus(401);
            return false;
        }
        try {
            getSubject(request, response).login(new JwtToken(jwt));
        } catch (UnknownAccountException e) {
            resp.setStatus(401);
            return false;
        }
        return true;
    }
}

完成以上步骤后,就可以通过前后端分离的方式,使用Shiro和JWT保护你的API了。

以上是Spring Boot整合Shiro+JWT实现前后端分离的完整攻略,其中包含两个示例:

  1. 编写登录接口
  2. 编写JWT过滤器

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Spring boot整合shiro+jwt实现前后端分离 - Python技术站

(0)
上一篇 2023年5月20日
下一篇 2023年5月20日

相关文章

  • 小程序实现带年月选取效果的日历

    下面是关于小程序实现带年月选取效果的日历的完整攻略: 一、实现思路 获取当前日期的年和月以及当月的天数; 使用数据渲染模板,并在相应的日期上添加样式; 实现滑动切换月份功能; 添加点击事件,实现从日历中选择日期并将该日期传递给父组件。 二、具体实现 下面我们将通过两个示例来说明具体实现步骤。 示例一 首先,我们需要在 wxml 文件中编写日历的结构,并通过 …

    Java 2023年5月23日
    00
  • Spring Data JPA 实现多表关联查询的示例代码

    下面是详细讲解 “Spring Data JPA 实现多表关联查询的示例代码” 的完整攻略。 1. 设置实体类之间的关联关系 在多表关联查询中,我们需要先设置实体类之间的关联关系,以让 JPA 知道它们之间的关联,从而能够生成正确的 SQL 语句。 在实体类中,我们可以使用 @ManyToOne、@OneToMany、@OneToOne、@ManyToMan…

    Java 2023年5月20日
    00
  • Nginx使用limit_req_zone对同一IP访问进行限流的方法

    下面将详细讲解“Nginx使用limit_req_zone对同一IP访问进行限流的方法”攻略。 简介 随着Web应用规模的不断增大和用户量的不断增多,对Web服务器的并发访问压力也越来越大。Nginx是一款高性能、高稳定性、低资源占用的Web服务器,常用于处理高并发请求。但在高并发情况下,同一IP对服务器的请求过多可能会引发服务器压力过大从而导致服务器响应缓…

    Java 2023年6月15日
    00
  • SpringBoot使用validation做参数校验说明

    下面是Spring Boot使用Validation做参数校验的攻略: 什么是Validation Validation是一种Java Bean Validation规范的实现,它提供了一种声明式验证的方式,可以在不依赖业务逻辑的情况下对请求参数进行校验,从而避免了代码重复和漏写校验的问题。 如何使用Validation 第一步:添加Validation依赖…

    Java 2023年5月20日
    00
  • 微信小程序 window_x64环境搭建

    当开发微信小程序时,需要在本地搭建开发环境,其中包括window_x64环境搭建。以下是完整的攻略。 Window_x64环境搭建 1. 下载安装Node.js 首先需要下载 Node.js 安装包并安装,Node.js 下载地址:https://nodejs.org/zh-cn/download/,安装时建议选择最新 LTS 版本。 安装完成后,打开命令行…

    Java 2023年5月23日
    00
  • spring-data-elasticsearch @Field注解无效的完美解决方案

    下面是“spring-data-elasticsearch @Field注解无效的完美解决方案”的完整攻略: 背景 在使用 Spring Data Elasticsearch 进行开发过程中,我们可能会遇到 @Field 注解无效的问题。这个问题可能会导致我们在使用 @Field 注解时无法正确添加到 Elasticsearch 的索引字段中。 解决方案 问…

    Java 2023年5月20日
    00
  • java多线程有序读取同一个文件

    要实现Java多线程有序读取同一个文件,可以使用以下步骤: 步骤一:打开文件流 首先,需要创建一个FileInputStream对象,该对象可以打开文件流并准备读取数据。代码示例如下: FileInputStream fis = new FileInputStream("file.txt"); 步骤二:创建 BufferedReader …

    Java 2023年5月19日
    00
  • 浅析Redis中String数据类型及其底层编码

    浅析Redis中String数据类型及其底层编码 String数据类型介绍 Redis中String数据类型是最基本、最常用的数据类型之一,它可以保存字符串、整数或者浮点数。String类型可以进行增删改查等常见操作,支持的操作包括SET、GET、INCR等。 String数据类型底层编码 Redis中,对于每一种数据类型,都有对应的底层编码方式,Strin…

    Java 2023年6月1日
    00
合作推广
合作推广
分享本页
返回顶部