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,也就说明认证成功了
相关推荐
SoaringHeart12 分钟前
Flutter最佳实践:IM聊天文字链接自动识别跳转
前端·flutter
掘金一周1 小时前
企业中要做智能体,最佳的方案是什么? | 沸点周刊 6.18
前端·人工智能·ai编程
Darling噜啦啦1 小时前
CSS 3D 变换与 Flex 布局实战:从零打造旋转立方体
前端·css
秃头网友小李1 小时前
前端难点:keep-alive 缓存什么?RouterView 的 key 为什么要带 scopeId?
前端·vue.js
鱼人1 小时前
CSS 变量:一个变量救你一百次复制粘贴
前端
长大19881 小时前
CSS 到底是什么?和 HTML 的区别一次讲清楚
前端
禅思院1 小时前
路由性能优化终极指南:从懒加载漏洞到边缘渲染的架构跃迁
前端·架构·前端框架
怕浪猫1 小时前
Electron 开发实战(十六):总结与展望|生态现状、框架对比、行业趋势与学习指南
前端·javascript·electron
文心快码BaiduComate1 小时前
Comate 搭载GLM-5.2:百万上下文,稳定支撑长程任务
前端·程序员·开源
星栈2 小时前
Dioxus 的 `rsx!` 语法:如果你会 React,上手确实特别快
前端·前端框架