毫无存在的沉默之路——初窥spring security,springboot集成spring security

SpringBoot Actuator未授权访问漏洞:原理、检测与防护实战指南 在微服务架构中,应用监控与管理端点是保障系统可观测性的核心组件。SpringBoot Actuator模块通过提供丰富的内置端点,实现了对应用健康状态、性能指标和环境配置的便捷监控。其工作原理基于“约定大于配置”的理念,默认暴露部分端点以提升开发效率。然而,若缺乏恰当的访问控制,这些端点将直接暴露敏感信息,如数据库连接字符串和API密钥,从而引发严重的安全风险。该漏洞的利用门槛极低,攻击者无需复杂技术即可获取内存转储文件或动态修改日志级别,实现静默信息搜集。在应用场景上,无论是传统单体应用还是云原生微服务, 阅读详情

1 spring boot集成spring security

1.1 初始化工程

数据库

创建一个 t_member 表存储用户信息

DROP TABLE IF EXISTS `t_member`;
CREATE TABLE `t_member`  (
  `id` int NOT NULL AUTO_INCREMENT,
  `username` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `password` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 2 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;

SET FOREIGN_KEY_CHECKS = 1;


INSERT INTO `t_member` (`id`, `username`, `password`) VALUES (1, 'admin', '123456');
INSERT INTO `t_member` (`id`, `username`, `password`) VALUES (2, 'yuwen', '123456');
INSERT INTO `t_member` (`id`, `username`, `password`) VALUES (3, 'yulei', '123456');

pom.xml

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

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

        <!--mybatis-spring-boot-starter-->
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.1.3</version>
        </dependency>

        <!--lombok-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>

        <!--fastjson-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.75</version>
        </dependency>

        <!--mysql-connector-java-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
    </dependencies>

application.yml

server:
  port: 8080

spring:
  datasource:
    url: jdbc:mysql://10.19.11.107:3306/demo-all?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai
    username: root
    password: root
    driver-class-name: com.mysql.cj.jdbc.Driver
  main:
    allow-bean-definition-overriding: true

mybatis:
  type-aliases-package: com.example.demooauth2authorization.dao
  configuration:
    map-underscore-to-camel-case: true
  mapper-locations: classpath:mapper/*.xml

logging:
  level:
    root: info
    com.example.demooauth2authorization.dao: debug

MemberController.java

@RestController
public class MemberController {

    @Autowired
    private MemberDao memberDao;

    /**
     * 查询所有用户
     *
     * @return List<User>
     */
    @GetMapping("getAll")
    public List<Member> getAll() {
        return memberDao.getAll();
    }

}

MemberDao.java

public interface MemberDao {

    /**
     * 查询所有用户
     *
     * @return List<User>
     */
    List<Member> getAll();
}

Member.java 

@Data
public class Member {

    private Integer id;

    private String username;

    private String password;
}

MemberDao.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<!-- 映射文件,映射到对应的SQL接口 -->
<mapper namespace="com.example.demooauth2authorization.dao.MemberDao">

    <!--查询所有用户-->
    <select id="getAll" resultType="com.example.demooauth2authorization.entity.Member">
        select *
        from t_Member
    </select>

    <!--根据用户名获取用户-->
    <select id="getUser" resultType="com.example.demooauth2authorization.entity.Member">
        select *
        from t_Member
        where username = #{username}
    </select>

</mapper>

hah,没有service层,因为这是一个demo,怎么简单怎么来。

启动工程,访问:http://127.0.0.1:8080/getAll

可以看到数据正常展示。

1.2 集成spring security

加入依赖:

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

新建类实现UserDetailService接口重写loadUserByUsername方法。

 CustomUserDetailsServiceImpl.java

package com.example.demooauth2authorization.security;

import com.example.demooauth2authorization.dao.MemberDao;
import com.example.demooauth2authorization.entity.Member;
import com.example.demooauth2authorization.util.PasswordEncoderUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;

/**
 * @author 相柳
 * @date 2021/9/4
 */
@Component
@Slf4j
public class CustomUserDetailsServiceImpl implements UserDetailsService {

    @Autowired
    private MemberDao memberDao;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        log.info("调用loadUserByUsername");
        // 通过用户名从数据库获取用户信息
        Member member = memberDao.getUser(username);
        if (member == null) {
            throw new UsernameNotFoundException("用户不存在");
        }

        // 角色集合
        List<GrantedAuthority> roles = new ArrayList<>();
        return new User(
                member.getUsername(),
                // 因为数据库是明文,所以这里需加密密码
                PasswordEncoderUtil.encode(member.getPassword()),
                roles
        );
    }

}

PasswordEncoderUtil.java

package com.example.demooauth2authorization.util;

import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;

/**
 * @author 相柳
 * @date 2021/9/6
 */
public class PasswordEncoderUtil {
    public static Boolean matches(String raw, String encoded) {
        return new BCryptPasswordEncoder().matches(raw, encoded);
    }

    public static String encode(String raw) {
        return new BCryptPasswordEncoder().encode(raw);
    }
}

创建Security的配置类WebSecurityConfig继承WebSecurityConfigurerAdapter,并重写configure(auth)方法。

@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private CustomUserDetailsServiceImpl customUserDetailsService;

    /**
     * 指定加密方式
     */
    @Bean
    public PasswordEncoder passwordEncoder() {
        // 使用BCrypt加密密码
        return new BCryptPasswordEncoder();
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth
                // 从数据库读取的用户进行身份认证
                .userDetailsService(customUserDetailsService)
                .passwordEncoder(passwordEncoder());
    }
}

重启工程,再次访问:http://127.0.0.1:8080/getAll

出现如下登录界面,这是spring security默认的登录页。输入数据库中的用户信息,登录进入即可

 2 spring security的配置

2.1 自定义登录页

使用freemarker作为模板,加入依赖:

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

然后把登录界面和欢迎页面写好,

login.ftl

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <!-- The above 3 meta tags *must* come first in the head; any other head content must come *after* these tags -->
    <meta name="description" content="">
    <meta name="author" content="">

    <title>微服务统一认证</title>

    <link href="/css/bootstrap.min.css" rel="stylesheet">
    <link href="/css/signin.css" rel="stylesheet">
</head>

<body class="sign_body">
<div class="container form-margin-top">
    <form class="form-signin" action="/member/login" method="post" style="width: 300px;margin: 0px auto;">
        <h2 class="form-signin-heading" align="center">自定义统一认证系统</h2>
        <input type="text" name="username" class="form-control form-margin-top" placeholder="账号" required autofocus><br/>
        <input type="password" name="password" class="form-control" placeholder="密码" required><br/>
        <button class="btn btn-lg btn-primary btn-block" type="submit">sign in</button><br/>
        <#if error??>
            <span style="color: red; ">${error}</span>
        </#if>
    </form>
</div>
</body>
</html>

welcome.ftl

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <!-- The above 3 meta tags *must* come first in the head; any other head content must come *after* these tags -->
    <meta name="description" content="">
    <meta name="author" content="">

    <title>微服务统一认证</title>

    <link href="/css/bootstrap.min.css" rel="stylesheet">
    <link href="/css/signin.css" rel="stylesheet">
</head>

<body class="sign_body">
<div class="container form-margin-top">
    尊敬的:<span style="color: red">
        <#if username??>
            ${username}
        </#if>
    </span>,欢迎您
</div>
</body>
</html>

自定义 LoginValidProvider 继承自 AuthenticationProvider。实现认证逻辑

LoginValidProvider.java

package com.example.demooauth2authorization.security;

import com.example.demooauth2authorization.dao.MemberDao;
import com.example.demooauth2authorization.entity.Member;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.stereotype.Component;

import java.util.ArrayList;

/**
 * @author 相柳
 * @date 2021/9/6
 */

@Component
@Slf4j
public class LoginValidProvider implements AuthenticationProvider {

    @Autowired
    private MemberDao memberDao;

    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        log.info("身份认证开始工作");
        String username = authentication.getName();
        String rawPassword = (String) authentication.getCredentials();

        // 数据库中查询用户
        Member member = memberDao.selectByUnameAndUPass(username, rawPassword);
        if (member != null) {
            return new UsernamePasswordAuthenticationToken(member, rawPassword, new ArrayList<>());
        } else {
            throw new BadCredentialsException("用户名或者密码错误");
        }
    }

    @Override
    public boolean supports(Class<?> authentication) {
        return true;
    }
}

然后自定义认证成功、认证失败和登出的处理函数(这是可选的)

LoginSuccessHandle.java

package com.example.demooauth2authorization.security;

import lombok.extern.slf4j.Slf4j;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.stereotype.Component;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * @author 相柳
 * @date 2021/9/6
 */
@Slf4j
@Component
public class LoginSuccessHandle implements AuthenticationSuccessHandler {

    @Override
    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
        log.info("进入登录成功handle");
        response.sendRedirect("/member/toWelcome");
    }
}

LoginFailHandle.java

package com.example.demooauth2authorization.security;

import lombok.extern.slf4j.Slf4j;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.stereotype.Component;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URLEncoder;

/**
 * @author 相柳
 * @date 2021/9/7
 */
@Slf4j
@Component
public class LoginFailHandle implements AuthenticationFailureHandler {

    @Override
    public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {
        log.info("进入登录失败handle");
        String toLogin = "/member/toLogin?error=";
        String url = toLogin + URLEncoder.encode(exception.getMessage(), "UTF-8");
        response.sendRedirect(url);
    }

}

LogoutHandle.java

package com.example.demooauth2authorization.security;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.http.HttpHeaders;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;
import org.springframework.stereotype.Component;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * @author 相柳
 * @date 2021/9/7
 */
@Slf4j
@Component
public class LogoutHandle implements LogoutSuccessHandler {

    @Override
    public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
        log.info("登出handle");
        // 获取请求参数中是否包含回调地址
        String redirectUrl = request.getParameter("redirect_url");
        if (StringUtils.isNotBlank(redirectUrl)) {
            response.sendRedirect(redirectUrl);
        }
        else {
            // 默认跳转referer 地址
            String referer = request.getHeader(HttpHeaders.REFERER);
            response.sendRedirect(referer);
        }
    }
}

接下来配置 WebSecurityConfig.java 。这是最重要的

package com.example.demooauth2authorization.security;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
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.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;

/**
 * @author 相柳
 * @date 2021/9/4
 */
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private LoginValidProvider loginValidProvider;

    @Autowired
    private LoginSuccessHandle loginSuccessHandle;

    @Autowired
    private LoginFailHandle loginFailHandle;

    @Autowired
    private LogoutHandle logoutHandle;

    @Bean
    @Override
    protected AuthenticationManager authenticationManager() throws Exception {
        return super.authenticationManager();
    }

    /**
     * 指定加密方式
     */
    @Bean
    public PasswordEncoder passwordEncoder() {
        // 使用BCrypt加密密码
        return new BCryptPasswordEncoder();
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        String toLogin = "/member/toLogin";
        String checkPath = "/member/login";
        http
                // 自定义登录页
                .formLogin()
                // 登录表单提交的url,即和form的action一致
                .loginProcessingUrl(checkPath)
                // 访问登录页的url
                .loginPage(toLogin)

                // 设置登录成功和失败的处理器
                .successHandler(loginSuccessHandle)
                .failureHandler(loginFailHandle)

                // 设置登出操作
                .and().logout()
                .logoutSuccessHandler(logoutHandle)
                .deleteCookies("JSESSIONID").invalidateHttpSession(true)

                // 登录请求不需要认证
                .and().authorizeRequests().antMatchers(toLogin).permitAll()

                // 其他的所有请求都需要认证
                .anyRequest().authenticated()

                // 关闭csrf防护
                .and().csrf().disable();
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        // 设置自定义认证
        auth.authenticationProvider(loginValidProvider);
    }
}

2.2 登录成功自动跳转到登录前的地址

改造之前的 LoginSuccesshandle.java

package com.example.demooauth2authorization.security;

import lombok.extern.slf4j.Slf4j;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.WebAttributes;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.security.web.savedrequest.HttpSessionRequestCache;
import org.springframework.security.web.savedrequest.RequestCache;
import org.springframework.security.web.savedrequest.SavedRequest;
import org.springframework.stereotype.Component;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;

/**
 * @author 相柳
 * @date 2021/9/6
 */
@Slf4j
@Component
public class LoginSuccessHandle implements AuthenticationSuccessHandler {

    @Override
    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
        log.info("进入登录成功handle");
        RequestCache requestCache = new HttpSessionRequestCache();
        SavedRequest savedRequest = requestCache.getRequest(request, response);
        if (savedRequest == null) {
            response.sendRedirect("/member/toWelcome");
            return;
        }
        // 返回之前请求的地址
        clearAuthenticationAttributes(request);
        String targetUrl = savedRequest.getRedirectUrl();
        response.sendRedirect(targetUrl);
    }

    protected final void clearAuthenticationAttributes(HttpServletRequest request) {
        HttpSession session = request.getSession(false);
        if (session != null) {
            session.removeAttribute(WebAttributes.AUTHENTICATION_EXCEPTION);
        }
    }
}

这段代码是仿照 spring security 内置的 SavedRequestAwareAuthenticationSuccessHandler 所写。SavedRequestAwareAuthenticationSuccessHandler 也有在登录后返回原来请求地址的作用。所以登录成功的处理逻辑也可以去继承它来实现跳转到之前的页面

--------------------------------------------------------

这篇博客是我看博客,看文档,看源码,然后结合一个开源项目和自身4年开发经验写出来的,仅供参考,留以备忘。

SpringBoot日志配置实战:从基础到生产级最佳实践 日志是应用可观测性的基石,其核心在于记录程序运行状态,便于问题追踪与系统监控。在Java生态中,SLF4J作为日志门面提供了统一的API,而Logback等则是其具体实现,这种抽象与实现分离的设计确保了代码的灵活性与可维护性。SpringBoot通过约定优于配置简化了日志集成,但深入理解其配置体系对于构建高效、稳定的生产环境至关重要。合理的日志配置能显著提升排查效率、降低系统负载,并保障数据安全。在微服务、分布式系统等场景下,日志更是链路追踪与性能分析的关键。本文将聚焦SpringBoot日志配置,深入解析 阅读详情

相关推荐

Jeecg-Boot生产级低代码平台部署与AI增强实践指南

低代码开发平台是现代企业数字化转型的关键基础设施,其核心在于平衡开发效率与系统可控性。Jeecg-Boot作为面向Spring Boot 3+与Vue3技术栈的生产级低代码引擎,通过元数据驱动、AI自然语言编程和可审计代码生成,将CRUD、权限、流程、报表等重复劳动压缩为配置化操作。它不仅支持零代码表单搭建,更提供可调试、可Merge的工程化低代码输出,并深度集成Flowable、MinIO、Sentinel、SkyWalking等企业级组件。在信创适配、微服务治理、安全加固及AI知识库RAG私有化等场景中

devon2014的博客 429

SpringSecurity实现自定义登录成功和登录失败处理器

实现:自定义处理器返回JSON数据,不进行页面跳转 一、自定义返回JSON数据类 自定义返回结果类 @Data @NoArgsConstructor @AllArgsConstructor public class Result<T> { /** * 状态码 */ private String code; /** * 状态信息 */ private String message; /** *

初栀的博客 1366

腾讯云CodingPlan实战指南:开箱即用的DevOps工程化路径

DevOps是现代软件交付的核心范式,其本质在于通过自动化流水线实现代码到服务的可靠、可追溯、可审计转化。腾讯云CodingPlan并非独立产品,而是深度集成CODING DevOps平台与腾讯云IaaS/PaaS服务的一套预置工程实践蓝图,聚焦环境一致性、云原生服务直连与合规性保障三大技术价值。它特别适用于Vue、Spring Boot等主流框架在腾讯云CVM、轻量应用服务器、COS及联络中心等场景的快速落地,有效解决‘腾讯云上传’‘vue项目web端如何接入腾讯云联络外呼’等高频实操断点,为中小团队和云

weixin_34203832的博客 376

(Spring Security)学习五:SuccessHandler成功登录及FailureHandler、LogoutSuccessHandler...等用法

一般成功登录后,需要触发一些操作,比如我们经常收到你异地登录的消息等,都是登录成功后触发的事务。SpringSecurity框架涵盖这部分。

希克的博客 2240

两年CRUD后端社招上岸:简历优化与高频面经实战复盘

在后端开发中,CRUD接口是业务系统的基础,但长期停留在“写接口、改接口”的层面,往往会在技术深度上遇到瓶颈。真正拉开工程师差距的,是对底层原理的理解、系统设计能力以及问题排查方法论——这些正是社招面试考察的核心维度。从Java集合源码、JVM内存模型、并发编程,到MySQL索引优化、Redis缓存一致性、SpringBoot自动配置原理,构建完整的知识体系,才能让项目经验经得起追问。本文从一线工程实践出发,梳理了从两年CRUD状态备战社招的完整路径:简历如何从“负责模块开发”改写为“场景—动作—结果”的项

weixin_30859423的博客 421

字节跳动后端实习面经:从笔试到HR面的全流程复盘与思考

后端开发岗位的面试,向来不只是考察CRUD能力,更看重对基础组件原理的深度理解。从MySQL的索引结构到MVCC实现,从Redis缓存一致性到Spring Boot自动配置原理,每一个常用技术点都可能成为追问链条的起点。本文从面试准备的技术价值出发,结合真实场景,梳理了从笔试、技术面到HR面的完整流程,围绕Java基础、MySQL、Redis、算法及项目深挖等高频考点,详细复盘了面试官的追问逻辑与回答思路。无论你即将投递后端实习岗位,还是想在Spring、MySQL、Redis等技术方向上查漏补缺,这份面经

weixin_30553777的博客 440

Spring Boot整合Spring Security + Redis实现用户认证

登录和用户认证是一个网站最基本的功能,在这篇博客里,将介绍如何用SpringBoot整合Spring Security + Redis实现登录及用户认证(~* - *)~

qq_57845086的博客 1152

ASP.NET Core中间件管道深度解析与实战避坑指南

ASP.NET Core中间件管道是理解请求生命周期的核心机制,其本质是由委托链构成的‘洋葱模型’执行流。掌握其原理需厘清Func<HttpContext, Func<Task>, Task>签名逻辑、next调用时机及短路行为,技术价值在于实现可预测、可诊断、可干预的HTTP处理流程。典型应用场景包括自定义认证授权、日志追踪、异常熔断与响应压缩等,而真实生产问题如JWT状态丢失、CORS预检失败、HTTPS重定向失效,往往根源于中间件注册顺序或上下文污染。本文聚焦C#泛型约束与协变逆变边界推导在中间件设计

diaojin6880的博客 396

Spring Security默认登录页面

使用Spring Security作为权限管理模块的小伙伴们一定醉心于其极少的配置即可满足权限管理需求,以及比springMVC更简洁的filter配置。 在刚开始技术验证的demo阶段相信很多人试过在什么都不配置的时候,只写个接口然后访问是会自动跳转到默认的登录页面"/login"。 按常理,一般人会好奇,这个登录页面在哪儿?应该是个模板引擎提供的模板,并且应该有个ModeAndView绑定的页面。 但实际上并不是。这个默认登录页面其实极其暴力简单。是一个默认filter里面直接写入response

ttaannkkee的博客 7684

学习SpringBoot使用SpringSecurity(一)_表单登录、角色认证以及SpringSecurity导致CSS样式丢失问题

文章目录一、 环境准备导入依赖创建数据库准备页面index.htmlhome.htmlyml配置文件实体类数据访问层业务层业务层实现类二、UserDetailsService三、WebSecurityConfigBug CSS样式丢失 一、 环境准备 用户认证一般要求用户提供用户名和密码。系统通过校验用户名和密码来完成认证过程。 用户授权指的是验证某个用户是否有权限执行某个操作。 spring security的主要核心功能为 认证和授权,所有的权限架构也是基于这两个核心功能去实现的。  “认证”,是为

DreamsArchitects的博客 1025

SpringBoot实现的高校招生全流程管理毕业设计资源包(含源码、视频、文档、SQL脚本)

这个SpringBoot招生管理系统专为本科毕业设计准备,用Java开发,后端基于MySQL数据库,完整覆盖招生业务场景:从首页信息展示、学生档案录入、专业与批次设置、在线报名登记、录取结果发布,到个人中心和后台权限管理。所有功能模块已集成调试完毕,支持Chrome、Firefox、Edge等主流浏览器访问,部署简单。压缩包里直接提供可导入IDEA或Eclipse的Maven项目源码(含pom.xml和标准src结构)、MP4格式操作演示视频、Word版开发说明文档、答辩用PPT、MySQL建库建表SQL脚

star5的专栏 219

Spring Boot2 实战系列之使用 Spring Security 实现登录

前言 在之前的一篇博文 Spring Boot2 实战系列之语言国际化 中利用了 BootStrap 官网的一个登录页面实现了语言国际化,这次在此之上进行改进,增加 Spring Security 的功能,使其能对登录用户进行认证。 Spring Boot 已经为 spring security 进行了自动配置,只需要引入以下依赖即可: <dependency> <groupId>org.springframework.boot</groupId> &lt

YekonGLE 1580

AD9361 Fast Lock实战:Python脚本自动生成Profile寄存器配置(附完整代码)

本文详细介绍了利用Python脚本实现AD9361 Fast Lock Profile寄存器自动化配置的实战方案。通过解析频率合成公式、VCO约束及查表机制,脚本能根据目标频率一键生成完整的16进制寄存器序列,大幅提升射频系统开发中多频点切换的效率和准确性,并支持CSV、JSON、C头文件等多种输出格式,便于与FPGA/嵌入式系统集成。

weixin_29194693的博客 475

上集:一个前端的血泪复仇记 —— 静态部署的胜利

在《上集:一个前端的血泪复仇记 —— 静态部署的胜利》中,作者分享了在部署一个前后端分离的小项目时遇到的挑战和解决方案。项目后端使用Spring Boot,前端使用Next.js。在部署过程中,前端静态资源的处理成为主要难题。作者通过将Next.js生成的静态文件直接放入Spring Boot的static目录,简化了部署流程。然而,Spring Security的默认配置阻止了对这些静态资源的访问,导致403错误。通过调整SecurityConfig和WebConfig,作者成功解决了这一问题。此外,前端

十步杀一人-千里不留行 2163

洪水风险图制作全流程:HEC-RAS 与 ArcGIS 的耦合应用

本文系统介绍HEC-RAS水动力模拟软件在水利工程中的应用技术。内容涵盖:1)软件理论与安装;2)一维地形数据导入与河网构建;3)恒定流/非恒定流计算及模型调试要点;4)构筑物建模技术(桥梁、堰闸等);5)二维水动力模拟与溃坝分析;6)洪水风险图绘制。重点讲解水面线调试、糙率选取、报错分析等实操难点,通过案例教学实现从基础到工程应用的全流程技术掌握。该培训适用于防洪评价、河道治理等水利工程数值模拟需求。

2403_89974123的博客 1054

ubuntu为Docker配置代理

我们平常在ubuntu终端中使用curl或git命令时,往往会很慢。所以,首先需要给ubuntu终端环境添加代理。查看自身那个软件的端口号,我这里是7890。

不想随波逐流的大学生一枚,我们每个人都在努力奔跑 1643

工作中使用到的单词(软件开发)

1.エイリアス   alias 别名 powershell使用 get-help 命令时,会得到与此命令 相关(别名)的命令 2.プロキシ proxy 代 理 3.プロモート   promote 促进,提升   开发的系统新功能上线发布,有时会使用到这个词,比如 STプロモート 还有使用リリース这个词的。比如STリリース。个人认为两者含义相同。 4.見逃し み................................................................

sun0322 6万+

使用ChIPSeeker进行ChIP-seq, ATAC-seq,cut&tag等富集峰的基因组注释

常规的下一代高通量测序(next generation sequencing, NGS)实验通常产生大量短片段(reads),通常我们需要将这些reads比对到参考基因组/转录组上,即将它们置于生物学上有意义的基因背景下,才能获得有意义的结果。一般我们认为会产生两种类型的数据(当然两者并无严格意义上的区分)

微生信 3320

工作中使用到的单词(软件开发)_第三版

====

sun0322 1万+

WinServer 2012 R2 搭建 AD 单域多站点 及 DNS各站点的子网掩码排序调整

WinServer 2012 R2 搭建 AD 单域多站点 及 DNS各站点的子网掩码排序调整

一直被模仿,从未被超越 5535

【上海大学计算机组成原理实验报告】一、数据传送实验

将58H写入A寄存器//将6BH写入W寄存器//将C3H写入R1寄存器//将C3H写入R1寄存器//了解实验仪器数据总线的控制方式//掌握数据传送的基本原理//掌握各寄存器的结构、工作原理及其控制方法//数据传送实验

HackerKevon的博客 3511

Java秋招面试全攻略:核心知识点与实战避坑指南

Java面试是后端开发者职业进阶的必经之路,其考察范围往往从基础概念延伸至工程实战。掌握HashMap底层原理、JVM内存模型、并发编程等核心知识,是构建完整技术体系的基石。理解这些原理不仅有助于应对八股文追问,更能指导开发者解决实际项目中的性能瓶颈。例如,通过合理配置线程池参数、优化索引策略,可以显著提升系统稳定性。在应用层面,接口安全对接、缓存穿透防护等场景,则考验候选人的设计能力。同时,环境配置问题如java环境变量配置、数组越界异常等,也常成为面试中的隐性障碍。本文从技术本质出发,系统梳理秋招Jav

weixin_34094282的博客 332

【银河麒麟桌面系统】安装英伟达(NVIDIA)显卡驱动

本文详细介绍了在麒麟桌面操作系统V10 SP1(版本号2503)上安装NVIDIA RTX 5060显卡驱动的完整流程。主要内容包括:查看系统版本信息,从NVIDIA官网下载Linux 64位驱动,授予执行权限后运行安装程序,处理安装过程中的X server警告、32位库安装、DKMS模块选择等问题,以及安装完成后如何验证驱动状态。同时提供了卸载驱动的步骤和常见问题解决方案,如处理X server警告、libglvnd EGL依赖问题等。该指南适用于需要在国产麒麟系统上安装NVIDIA显卡驱动的用户,包含完

信创运维工程师 · 银河麒麟 & 容器实战 | 金融生产环境迁移·等保加固 | 142篇原创·17万+阅读 6314

springboot security莫名其妙的登录界面Please sign in

spring boot集成security,启动项目不是出了自己的登录页面,而是下面莫名其妙的页面: 整了好久一直是这样,后来才发现其实这个是security默认给我们整的一个用户认证的功能,用户名是:user 密码是在启动的控制台打印出来的: 输入用户名和密码 登录进去报404 说明我们什么服务也没有配置,要想配置自己的认证 需要添加一个继承WebSecu...

gongli109的专栏 3万+

DeepSmote:一种深度SMOTE方法

DeepSmote 一种全新的将深度学习与Smote相结合的过采样方法! 目前在许多领域已经被使用,值得大家关注学习!

走在深度学习前沿的小宋 1447

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

基于spring boot和mongodb打造一套完整的权限架构(四)【完全集成security】

      在第二章的时候我们已经在我们的配置文件中设置了文件权限放行的功能,在本章我们将讲解如何基于mongodb数据库实现security,基于上一章我们编写的代码本章我们将实现security的权限控制。      1、首先在我们的sys的entity目录底下我们新建一个UserRole、User以及QueryUser实体类,类信息如下:package com.mongo.sys.entit...

笨鸟不会飞 1万+

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

上一篇: 秋老虎的灼热——elk流程打通
下一篇: 越挫越勇的进取之意——spring security集成jwt
Yuwen_forJava
博客等级 码龄9年 28粉丝 90原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值