SpringSecurity如何整合JWT

整合JWT

我们前几个小节,实现的是非前后端分离情况下的认证与授权的处理,目前大部分项目,都是使用前后端分离的模式。那么前后端分离的情况下,我们如何使用SpringSecurity来解决权限问题呢?最常见的方案就是SpringSecurity+JWT

认证流程
  • 同步认证:登录之后会自动被框架的过滤器拦截,然后或许用户信息进行认证

  • 前后端分离认证:自定义登录接口,主动调用框架进行认证,使用的是框架提供的认证管理器

认证实现
环境准备
  • 为了快速搞定环境,我们新创建一个项目springsecurity-jwt,注意把上一个demo工程的代码和pom都拷贝过来

  • 从zzyl-common模块中工具类JwtUtil拷贝到当前项目中 ,用于生成和验证 JWT令牌

pom文件依赖
java 复制代码
<!--JWT-->
<dependency>
    <groupId>com.auth0</groupId>
    <artifactId>java-jwt</artifactId>
    <version>3.8.1</version>
</dependency>
<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt</artifactId>
    <version>0.9.1</version>
</dependency>
<!--工具包-->
<dependency>
    <groupId>cn.hutool</groupId>
    <artifactId>hutool-all</artifactId>
    <version>5.8.0.M3</version>
</dependency>
<dependency>
    <groupId>javax.xml.bind</groupId>
    <artifactId>jaxb-api</artifactId>
</dependency>
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>1.2.75</version>
</dependency>
定义认证管理器

自定义授权管理属于全局,我们需要让它被spring容器进行管理,所以我们可以把它配置在SecurityConfig配置类中

在SecurityConfig添加创建认证管理器的代码,如下:

java 复制代码
package com.itheima.project.web;

import com.itheima.project.entity.LoginDto;
import com.itheima.project.entity.UserAuth;
import com.itheima.project.util.JwtUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.HashMap;
import java.util.Map;

/**
 * @author sjqn
 */
@RestController
@RequestMapping("/security")
public class LoginController {

    @Autowired
    private AuthenticationManager authenticationManager;

    @PostMapping("/login")
    public String login(@RequestBody LoginDto loginDto){

        //包装用户的密码
        UsernamePasswordAuthenticationToken upat = new UsernamePasswordAuthenticationToken(loginDto.getUsername(),loginDto.getPassword());

        //需要一个认证管理器,来进行调用
        Authentication authenticate = authenticationManager.authenticate(upat);
        //判断认证是否成功
        if(authenticate.isAuthenticated()){
            //获取用户
            UserAuth userAuth = (UserAuth) authenticate.getPrincipal();
            //认证成功
            //生成jwt,返回
            Map<String,Object> map = new HashMap<>();
            map.put("user",userAuth);

            String token = JwtUtil.createJWT("itcast", 360000, map);
            return token;
        }
        return "";

    }
}
登录功能实现

有了认证管理器之后,我们就可以在自己的登录接口中来使用认证管理器完成认证的操作

下面是自定义接口完成认证

java 复制代码
package com.itheima.project.web;

import com.itheima.project.entity.LoginDto;
import com.itheima.project.entity.UserAuth;
import com.itheima.project.util.JwtUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.HashMap;
import java.util.Map;

/**
 * @author sjqn
 */
@RestController
@RequestMapping("/security")
public class LoginController {

    @Autowired
    private AuthenticationManager authenticationManager;

    @PostMapping("/login")
    public String login(@RequestBody LoginDto loginDto){

        //包装用户的密码
        UsernamePasswordAuthenticationToken upat = new UsernamePasswordAuthenticationToken(loginDto.getUsername(),loginDto.getPassword());

        //需要一个认证管理器,来进行调用
        Authentication authenticate = authenticationManager.authenticate(upat);
        //判断认证是否成功
        if(authenticate.isAuthenticated()){
            //获取用户
            UserAuth userAuth = (UserAuth) authenticate.getPrincipal();
            //认证成功
            //生成jwt,返回
            Map<String,Object> map = new HashMap<>();
            map.put("user",userAuth);

            String token = JwtUtil.createJWT("itcast", 360000, map);
            return token;
        }
        return "";

    }
}

LoginDto

java 复制代码
package com.itheima.project.entity;

import lombok.Data;

@Data
public class LoginDto {

    private String username;
    private String password;
}

修改自定义配置,由于目前是接口开发,无需在使用自定义登录页面,只需要放行登录接口就行了

java 复制代码
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {

    //构建自定义配置
    http.authorizeHttpRequests().antMatchers("/security/login").permitAll();
    http.csrf().disable();
    return http.build();
}

测试

使用ApiFox测试

  • 输入正确的用户名和密码,则会返回jwt生成的token,也就说明认证成功了
相关推荐
腾讯TNTWeb前端团队4 小时前
helux v5 发布了,像pinia一样优雅地管理你的react状态吧
前端·javascript·react.js
mghio6 小时前
Dubbo 中的集群容错
java·微服务·dubbo
范文杰8 小时前
AI 时代如何更高效开发前端组件?21st.dev 给了一种答案
前端·ai编程
拉不动的猪8 小时前
刷刷题50(常见的js数据通信与渲染问题)
前端·javascript·面试
拉不动的猪8 小时前
JS多线程Webworks中的几种实战场景演示
前端·javascript·面试
FreeCultureBoy9 小时前
macOS 命令行 原生挂载 webdav 方法
前端
uhakadotcom9 小时前
Astro 框架:快速构建内容驱动型网站的利器
前端·javascript·面试
uhakadotcom10 小时前
了解Nest.js和Next.js:如何选择合适的框架
前端·javascript·面试
uhakadotcom10 小时前
React与Next.js:基础知识及应用场景
前端·面试·github