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,也就说明认证成功了
相关推荐
ai产品老杨2 分钟前
减少交通拥堵、提高效率、改善交通安全的智慧交通开源了。
前端·vue.js·算法·ecmascript·音视频
gaoliheng0062 分钟前
Redis看门狗机制
java·数据库·redis
我是唐青枫5 分钟前
.NET AOT 详解
java·服务器·.net
lexiangqicheng7 分钟前
JS-- for...in和for...of
开发语言·前端·javascript
我是老孙26 分钟前
windows10 php报错
开发语言·php
粥里有勺糖27 分钟前
视野修炼-技术周刊第122期 | 发光图片制作
前端·javascript·github
y1021210429 分钟前
Python训练营打卡Day42
开发语言·javascript·ecmascript
Su米苏29 分钟前
Axios请求超时重发机制
java
2301_8050545640 分钟前
Python训练营打卡Day46(2025.6.6)
开发语言·python
曹勖之1 小时前
撰写脚本,通过发布/joint_states话题改变机器人在Rviz中的关节角度
开发语言·python·机器人·ros2