SpringBoot最新版本Security配置(2023年),亲测成功

这篇具有很好参考价值的文章主要介绍了SpringBoot最新版本Security配置(2023年),亲测成功。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

SpringBoot最新版本Security配置(2023年),亲测成功

pom依赖:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.0.6</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.yw</groupId>
    <artifactId>reviewTest</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>reviewTest</name>
    <description>reviewTest</description>
    <properties>
        <java.version>17</java.version>
    </properties>
    <dependencies>

        <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-jdbc -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
            <version>3.0.2</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.26</version>
            <scope>provided</scope>
        </dependency>

        <!-- https://mvnrepository.com/artifact/com.mysql/mysql-connector-j -->
        <dependency>
            <groupId>com.mysql</groupId>
            <artifactId>mysql-connector-j</artifactId>
            <version>8.0.32</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/com.baomidou/mybatis-plus-boot-starter -->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.5.3</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/com.baomidou/mybatis-plus-generator -->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-generator</artifactId>
            <version>3.5.3.1</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-security -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
            <version>3.0.2</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/io.jsonwebtoken/jjwt-api -->
        <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt-api</artifactId>
            <version>0.11.5</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/io.jsonwebtoken/jjwt-impl -->
        <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt-impl</artifactId>
            <version>0.11.5</version>
            <scope>runtime</scope>
        </dependency>

        <!-- https://mvnrepository.com/artifact/io.jsonwebtoken/jjwt-jackson -->
        <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt-jackson</artifactId>
            <version>0.11.5</version>
            <scope>runtime</scope>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.jetbrains/annotations -->
        <dependency>
            <groupId>org.jetbrains</groupId>
            <artifactId>annotations</artifactId>
            <version>23.0.0</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-websocket</artifactId>
            <version>3.0.6</version>
        </dependency>

        <dependency>
            <groupId>com.alibaba.fastjson2</groupId>
            <artifactId>fastjson2</artifactId>
            <version>2.0.29</version>
        </dependency>

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

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

    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <excludes>
                        <exclude>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                        </exclude>
                    </excludes>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

application.properties

server.port=3000
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.url=jdbc:mysql://localhost:3307/kob?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf-8
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

SecurityConfig:

package com.yw.reviewtest.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityCustomizer;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.config.ldap.LdapBindAuthenticationManagerFactory;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;

/**
 * @author yw~
 * @version 1.0
 */
@Configuration
@EnableWebSecurity
public class SecurityConfig {
    @Autowired
    private JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter;

    // jwt 校验过滤器,从 http 头部 Authorization 字段读取 token 并校验
    @Bean
    public JwtAuthenticationTokenFilter authFilter() throws Exception {
        return new JwtAuthenticationTokenFilter();
    }
    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    /**
     * 获取AuthenticationManager(认证管理器),登录时认证使用
     *
     * @param authenticationConfiguration
     * @return
     * @throws Exception
     */
    @Bean
    public AuthenticationManager authenticationManager(AuthenticationConfiguration authenticationConfiguration) throws Exception {
        return authenticationConfiguration.getAuthenticationManager();
    }

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http
                // 基于 token,不需要 csrf
                .csrf().disable()
                // 基于 token,不需要 session
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
                // 前后端分离架构不需要csrf保护
                .authorizeHttpRequests(authorizeHttpRequests -> authorizeHttpRequests
                        // 允许所有OPTIONS请求
                        .requestMatchers(HttpMethod.OPTIONS, "/**").permitAll()
                        // 允许直接访问授权登录接口
                        //一般浏览器访问url为get请求,而前端请求设置中为post,增加安全
                        .requestMatchers(HttpMethod.POST, "/user/account/token/").permitAll()
                        // 允许 SpringMVC 的默认错误地址匿名访问
                        .requestMatchers("/error").permitAll()
                        // 其他所有接口必须有Authority信息,Authority在登录成功后的UserDetailsImpl对象中默认设置“ROLE_USER”
                        //.requestMatchers("/**").hasAnyAuthority("ROLE_USER")
                        // 所有请求将会拦截,除了已经登录
                        .anyRequest().authenticated()
                );
        //这里默认为security登录页面,在后续需要关闭时进行
        // 添加 JWT 过滤器,JWT 过滤器在用户名密码认证过滤器之前
       http.addFilterBefore(authFilter(), UsernamePasswordAuthenticationFilter.class);
        //使配置生效
        return http.build();
    }

    @Bean
    public WebSecurityCustomizer webSecurityCustomizer() {
        // 将前端请求全双工放行
        //使用WebSecurity.ignoring()忽略某些URL请求,这些请求将被Spring Security忽略,这意味着这些URL将有受到 CSRF、XSS、Clickjacking 等攻击的可能。
        return (web) -> web.ignoring().requestMatchers("/websocket/**");
    }
    /**
     * 配置跨源访问(CORS)
     * @return
     */
    @Bean
    public CorsFilter corsFilter() {
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        CorsConfiguration corsConfiguration = new CorsConfiguration();
        corsConfiguration.addAllowedOriginPattern("*");
        corsConfiguration.addAllowedHeader("*");
        corsConfiguration.addAllowedMethod("*");
        corsConfiguration.setAllowCredentials(true);
        source.registerCorsConfiguration("/**", corsConfiguration);
        return new CorsFilter(source);
    }
}

配置默认登录用户(即用数据库的用户和密码登录):

1:UserDetailsServiceImpl

package com.yw.reviewtest.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.yw.reviewtest.mapper.UserMapper;
import com.yw.reviewtest.pojo.User;
import com.yw.reviewtest.utils.UserDetailsImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;

/**
 * @author yw~
 * @version 1.0
 */
@Service
public class UserDetailsServiceImpl implements UserDetailsService {
    @Autowired
    private UserMapper userMapper;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        QueryWrapper<User> queryWrapper = new QueryWrapper();
        queryWrapper.eq("username", username);
        User user = userMapper.selectOne(queryWrapper);
        if (user == null) {
            throw new UsernameNotFoundException("用户不存在");
        }
        return new UserDetailsImpl(user);
    }
}

2:UserDetailsImpl:

package com.yw.reviewtest.utils;

import com.yw.reviewtest.pojo.User;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.security.core.GrantedAuthority;

import org.springframework.security.core.userdetails.UserDetails;

import java.util.Collection;

/**
 * @author yw~
 * @version 1.0
 */
@Data
@AllArgsConstructor
@NoArgsConstructor
public class UserDetailsImpl implements UserDetails {
    private User user;

    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        return null;
    }

    @Override
    public String getPassword() {
        return user.getPassword();
    }

    @Override
    public String getUsername() {
        return user.getUsername();
    }

    @Override
    public boolean isAccountNonExpired() {
        return true;
    }

    @Override
    public boolean isAccountNonLocked() {
        return true;
    }

    @Override
    public boolean isCredentialsNonExpired() {
        return true;
    }

    @Override
    public boolean isEnabled() {
        return true;
    }
}

3:配置完,记得更改SecurityConfig配置,添加前端密码加密验证,

因为security默认密码加密为{noop}+密码

在用户进行用户认证登录的时候,前端传来的密码会用BCrpt加密方式进行加密,加密后的密码格式是{id}password,然后程序员会先获取到加密方式也即是{id},假设没有写passwordEncoder(new BCryptPasswordEncoder())那么前端传来的值就不会用BCrpt加密方式进行加密,所以程序员获取前端传来的值时是寻找不到密码中的{id}也即是加密方式的,因此就会报There is no PasswordEcoder mapped for the id "null"异常。

@Bean
public PasswordEncoder passwordEncoder() {
 return new BCryptPasswordEncoder();
}

jwt:

第一次前端登录,调取后端接口,发送账号和密码,

后端接收到判断和数据库信息是否相同,相同则根据用户或者用户id生成一个jwt返回给前端,

前端接收到jwt存储到本地并跳转相应页面

前端每次跳转页面时都会携带该jwt发送给后端,后端都将对该jwt进行解析

解析成对应用户id来获得相应权限,jwt验证成功就返回给前端数据

如果jwt解析过期或者失败,就返回前端401,前端接收到就清除jwt然后返回登录页面

这里就可以使用security自带登录对数据库信息进行验证登录了

JWT配置:

jwtUtil:

通过该工具类根据用户id生成jwt

//将userId封装成JWTtoken
String jwt= JwtUtil.createJWT(user.getId().toString());
// utils.JwtUtil
//为jwt工具类,用来创建、解析 jwt_token
//作用是将我们的字符串加上密钥加上有效期变成一个加密后的字符串
//另外一个作用是给我们一个令牌让我们把她的有效期解析出来
package com.yw.reviewtest.utils;


import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.springframework.stereotype.Component;

import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.util.Base64;
import java.util.Date;
import java.util.UUID;


@Component
public class JwtUtil {
    // 有效期14天
    public static final long JWT_TTL = 60 * 60 * 1000L * 24 * 14;

    // 密钥,内容是随机字符串,长度必须足够长,只能是大小写英文和数字
    public static final String JWT_KEY = "SDFGjhdsfalshdfHFdsjkdsfds121232131afasdfac";

    //
    public static String getUUID() {
        return UUID.randomUUID().toString().replaceAll("-", "");
    }

    public static String createJWT(String subject) {
        JwtBuilder builder = getJwtBuilder(subject, null, getUUID());
        return builder.compact();
    }

    private static JwtBuilder getJwtBuilder(String subject, Long ttlMillis, String uuid) {
        SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;
        SecretKey secretKey = generalKey();
        long nowMillis = System.currentTimeMillis();
        Date now = new Date(nowMillis);
        if (ttlMillis == null) {
            ttlMillis = JwtUtil.JWT_TTL;
        }

        long expMillis = nowMillis + ttlMillis;
        Date expDate = new Date(expMillis);
        return Jwts.builder()
                .setId(uuid)
                .setSubject(subject)
                .setIssuer("sg")
                .setIssuedAt(now)
                .signWith(signatureAlgorithm, secretKey)
                .setExpiration(expDate);
    }

    public static SecretKey generalKey() {
        byte[] encodeKey = Base64.getDecoder().decode(JwtUtil.JWT_KEY);
        return new SecretKeySpec(encodeKey, 0, encodeKey.length, "HmacSHA256");
    }

    public static Claims parseJWT(String jwt) throws Exception {
        SecretKey secretKey = generalKey();
        return Jwts.parserBuilder()
                .setSigningKey(secretKey)
                .build()
                .parseClaimsJws(jwt)
                .getBody();
    }
}

JwtAuthenticationTokenFilter:

客户端的请求头里携带了 token,服务端肯定是需要针对每次请求解析校验 token 的,所以必须得定义一个过滤器,也就是 JwtAuthenticationTokenFilter:

  • 从请求头中获取 token
  • 对 token 进行解析、验签、校验过期时间
  • 校验成功,将验证结果放到 ThreadLocal 中,供下次请求使用
package com.yw.reviewtest.config;

import com.yw.reviewtest.mapper.UserMapper;
import com.yw.reviewtest.pojo.User;
import com.yw.reviewtest.utils.JwtUtil;
import com.yw.reviewtest.utils.UserDetailsImpl;
import io.jsonwebtoken.Claims;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.filter.OncePerRequestFilter;

import java.io.IOException;

/**
 * @author yw~
 * @version 1.0
 */
@Component
public class JwtAuthenticationConfig extends OncePerRequestFilter {
    @Autowired
    private UserMapper userMapper;
    @Override
    protected void doFilterInternal(HttpServletRequest request, @NotNull HttpServletResponse response, @NotNull FilterChain filterChain) throws ServletException, IOException {
        String token = request.getHeader("Authorization");

        if (!StringUtils.hasText(token) || !token.startsWith("Bearer ")) {
            filterChain.doFilter(request, response);
            return;
        }

        token = token.substring(7);

        String userid;
        try {
            Claims claims = JwtUtil.parseJWT(token);
            userid = claims.getSubject();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }

        User user = userMapper.selectById(Integer.parseInt(userid));

        if (user == null) {
            throw new RuntimeException("用户名未登录");
        }

        UserDetailsImpl loginUser = new UserDetailsImpl(user);
        UsernamePasswordAuthenticationToken authenticationToken =
                new UsernamePasswordAuthenticationToken(loginUser, null, null);

        SecurityContextHolder.getContext().setAuthentication(authenticationToken);

        filterChain.doFilter(request, response);
    }
}

跨域问题:

这里使用在Securitty里面配置了文章来源地址https://www.toymoban.com/news/detail-630148.html

到了这里,关于SpringBoot最新版本Security配置(2023年),亲测成功的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • docker容器运行成功但无法访问,原因分析及对应解决方案(最新,以Tomcat为例,亲测有效)

    原因分析:     是否能访问当运行docker容器虚拟机(主机)地址     虚拟机对应的端口号是否开启或者防墙是否关闭     端口映射是否正确(这个是我遇到的)     tomcat下载的是最新版,docker运行后里面是没有东西的,会报404 一般都是这几个原因导致的明明docker容器运行

    2024年02月10日
    浏览(42)
  • JDK、IDEA安装教程 IDEA安装2023年10月 最新最详细!免费、亲测成功!!!

    以下是第一章的内容: IntelliJ IDEA安装教程 文章目录 前言 准备工作 步骤(敲详细!!!) IDEA的安装是Java课程的入门,本人台式机于2023年7月份进行了系统重装,恰巧最近需要重新安装IDEA进行使用,借此机会给同学们分享我的安装过程(昔日的安装过程依稀记得,这次是边

    2024年02月04日
    浏览(49)
  • 2023 年 Pycharm 最新安装教程,亲测可用

    PyCharm 是一款功能强大的 Python 编辑器,具有跨平台性,鉴于目前最新版 PyCharm 使用教程较少,为了节约时间,来介绍一下 PyCharm 在 Windows下是如何安装的。 这是 PyCharm 的下载地址:http://www.jetbrains.com/pycharm/download/#section=windows 进入该网站后,我们会看到如下界面: professional 表

    2024年02月08日
    浏览(52)
  • 最新mac切换php版本(升版本和降版本)亲测有效

    由于公司新业务的项目与老项目PHP环境版本不一致,导致一部分老项目刚接手过来环境运行不起来,涉及到PHP版本切换,包括升版本和降版本问题的解决 查看电脑已经运行的PHP版本  可以看到mac下brew安装的服务程序 刚接手的项目却要7.0版本的PHP,方法大概有五种方法(莫执行

    2024年02月12日
    浏览(46)
  • 小程序逆向工程:这个开源的小程序逆向工具真不错,2023年亲测成功

    安全部门的大哥又双叒叕报了一个小程序的高危漏洞,他使用逆向工程破解了加密信心,用抓包修改了请求参数。又是头疼的一天… 想成为一名微信小程序的开发者,前端思路的学习和安全意识是非常有必要的,故务必掌握小程序反编译技能。 这里用到了2个工具《解密》与

    2023年04月19日
    浏览(61)
  • 2023 年 Pycharm 最新下载安装教程,亲测可用,持续更新

    PyCharm 是一款功能强大的 Python 编辑器,具有跨平台性,鉴于目前最新版 PyCharm 使用教程较少,为了节约时间,来介绍一下 PyCharm 在 Windows下是如何安装的。 这是 PyCharm 的下载地址:http://www.jetbrains.com/pycharm/download/#section=windows 进入该网站后,我们会看到如下界面: professional 表

    2024年02月13日
    浏览(96)
  • Maven《二》-- Maven的安装与配置(亲测成功版)

    目录 🐶2.1 Maven的安装条件 🐶2.2 Maven安装步骤 1. 检查本地%JAVA_HOME%  2. 解压maven 3. 配置maven的环境变量 4. 校验maven是否配置成功 5. 配置本地仓库 🐶2.3 Idea配置本地Maven软件 各个工具选用版本: 工具 版本 Maven 3.8.3 JDK 18 IDEA 2021.1.3 安装条件 :maven需要本机安装java环境、必需包

    2024年01月19日
    浏览(38)
  • 【网络安全零基础入门】003、2023最新kali下载安装教程(超详细,亲测可用)

    虚拟机安装(这里我使用VMware17),如果不会安装虚拟机的朋友可以看看下面这篇教程,亲测可用 【网络安全修炼-炼气期】001、Win10环境下VMware17的下载与安装(超详细,亲测可用) 我们进入kali官网,选择Installer Images 可根据自己需求选择64位,32位。 下载完成后的镜像如下图所

    2024年02月08日
    浏览(63)
  • 最新版本!亲测有效!ES_7.17.9安装教程(破解白金版、kibana安装)

    1.修改服务器相关配置 1)永久关闭防火墙 2)修改主机名 3)配置主机间通 4)ssh免密配置 5)修改最大可创建文件数大小 6)修改最大虚拟内存大小 2.ES安装前期准备 1)创建es用户 2)创建es文件夹,并在其下创建data和logs文件夹 3)为用户授权es文件操作权限 3.ES解压安装 4.修改

    2024年02月08日
    浏览(48)
  • 2023版本idea使用maven新建web项目(亲测不报错)

    1.新建项目——选择maven Archetype然后在Archetype选择webapp——选择创建 2.直接选择创建,等待maven加载完,就可以, 3.然后我们找到左上角选择编辑配置,    4.添加tomcat,选择加号,然后选择本地,  5.再点击修正,应用,就添加成功了   最后再启动一下,页面出现hello world就

    2024年02月11日
    浏览(56)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包