Spring Security 简单token配置

Spring Security 简单token配置

说明:非表单配置

先上码: https://gitee.com/qkzztx_admin/security-demo/tree/master/demo-two

环境:win10 idea2023 springboot2.7.6 maven3.8.6

代码清单说明

依赖:

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

Spring Security配置:

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
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.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;import javax.annotation.Resource;@Configuration
@EnableWebSecurity
@EnableMethodSecurity
public class SecurityConfig {@Resourceprivate MyAccessDeniedHandler myAccessDeniedHandler;@Resourceprivate MyAuthenticationEntryPoint myAuthenticationEntryPoint;@Resourceprivate AuthFilter authFilter;/*** security配置*/@Beanpublic SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {http.csrf().disable() // 禁用csrf.authorizeRequests().antMatchers("/login").permitAll() // 允许任何人访问登录接口.and().sessionManagement(sessionManager -> sessionManager.sessionCreationPolicy(SessionCreationPolicy.STATELESS)) // 不再管理session.authorizeRequests().anyRequest().authenticated() // 除了所有允许匿名访问的接口外,任何其他接口都得先认证.and().exceptionHandling(handling -> {handling.accessDeniedHandler(myAccessDeniedHandler) // 访问被拒绝的处理器.authenticationEntryPoint(myAuthenticationEntryPoint); // 认证失败的处理入口});// 设置用户访问前filterhttp.addFilterBefore(authFilter, UsernamePasswordAuthenticationFilter.class);return http.build();}/*** 用户数据*/@Beanpublic InMemoryUserDetailsManager userDetailsService() {UserDetails user = User.builder().username("user").password(passwordEncoder().encode("password")).roles("USER").build();return new InMemoryUserDetailsManager(user);}/*** 密码加密类*/@Beanpublic PasswordEncoder passwordEncoder() {return new BCryptPasswordEncoder();}}

放开/login的访问,方便用户认证,也就是抛弃了spring security的默认认证接口。
配置中,还有简单的用户查询服务,和一个默认的密码加密Bean。

import com.example.demo.two.controller.vo.R;
import com.example.demo.two.controller.vo.UserRequest;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;import javax.annotation.Resource;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.UUID;@RestController
public class LoginController {/*** 简单的存放用户登录认证成功信息的地方*/public final static Map<String, UserDetails> TOKEN_USERNAME = new HashMap<>();/*** SecurityConfig中配置的userDetailsService*/@Resourceprivate UserDetailsService userDetailsService;/*** SecurityConfig中配置的密码加密*/@Resourceprivate PasswordEncoder passwordEncoder;/*** 登录认证,获得token* @param userRequest 用户名和密码* @return 认证token*/@PostMapping("/login")public R login(@RequestBody UserRequest userRequest) {UserDetails userDetails = userDetailsService.loadUserByUsername(userRequest.getUsername());if (Objects.isNull(userDetails)) {return R.fail("用户名不存在");}if(passwordEncoder.matches(userRequest.getPassword(), userDetails.getPassword())) {// 认证成功发个tokenString token = UUID.randomUUID().toString();// 认证成功信息,简单存储TOKEN_USERNAME.put(token, userDetails);return R.success("登录成功", token);}return R.fail("密码不正确");}@GetMapping("/")public String index() {return "首页";}
}

简单的认证接口,注入了用户查询服务和密码加密Bean。
查询用户,判断密码,生成token,保存token,返回token,很简单。
还有一个首页接口是需要认证才能访问。

访问资源无权限时的处理类

import com.example.demo.two.controller.vo.R;
import com.example.demo.two.util.SimpleResponseUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.web.access.AccessDeniedHandler;
import org.springframework.stereotype.Component;import javax.annotation.Resource;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;@Slf4j
@Component
public class MyAccessDeniedHandler implements AccessDeniedHandler {@Resourceprivate SimpleResponseUtil simpleResponseUtil;@Overridepublic void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException, ServletException {// 无权限,一般返回403log.info("拒绝访问:{}", accessDeniedException.getMessage());simpleResponseUtil.write(response, R.fail("拒绝访问"));}
}

未登录访问资源时的处理类

import com.example.demo.two.controller.vo.R;
import com.example.demo.two.util.SimpleResponseUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.stereotype.Component;import javax.annotation.Resource;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;@Slf4j
@Component
public class MyAuthenticationEntryPoint implements AuthenticationEntryPoint {@Resourceprivate SimpleResponseUtil simpleResponseUtil;@Overridepublic void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException {// 未认证,一般返回401log.info("未认证: {}", authException.getMessage());simpleResponseUtil.write(response, R.fail("未认证,请先认证"));}
}

自定义过滤器,以便识别用户身份,把用户身份设置到线程上下文中

import com.example.demo.two.controller.LoginController;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.filter.OncePerRequestFilter;import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Objects;@Slf4j
@Component
public class AuthFilter extends OncePerRequestFilter {@Overrideprotected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {// 比如请求头中有个header叫token,放置了认证后的请求头String token = request.getHeader("token");log.info("用户token:{}", token);if (StringUtils.hasText(token)) {// 验证token是否已经登录了的用户的token,用户的token临时放在了LoginControllerUserDetails userDetails = LoginController.TOKEN_USERNAME.get(token);if (Objects.nonNull(userDetails)) {// 有,表示token是对的,设置线程上下文认证信息,然后访问其他资源时,security就会放行UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(userDetails.getUsername(), userDetails.getPassword(), userDetails.getAuthorities());SecurityContextHolder.getContext().setAuthentication(authenticationToken);}}filterChain.doFilter(request, response);}
}

验证效果

未认证前访问首页:
在这里插入图片描述
在这里插入图片描述

登录认证:

在这里插入图片描述
认证成功后,把得到的token放入请求头中,再请求
在这里插入图片描述
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/121054.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

算法的时间复杂度分析习题专题

之前写了一篇重点是讲理论&#xff0c;今天重点在于对于题目的分析 题目难度不分先后&#xff0c;有题目来源会直接给出链接或者位置 第一题&#xff1a;消失的数字 题目来源&#xff1a;LeetCode消失的数字 分析 第一种思路分析&#xff1a; 参考代码&#xff1a; #include …

CTP:关于cc和bindgen库及rust工程组织

有三个工程目录&#xff0c;cpt-api, ctp-sdk,ctp-strategy 1、ctp-sdk&#xff1a; 主要的目的是基于bindgen库生成与cpp的.h文件相对应一个binding.rs文件&#xff0c;后面供策略使用。 在这个目录下&#xff0c;建一个build.rs,用bindgen库生成cpp.h的头文件相应的rust绑定…

nodejs+vue 网上招聘系统elementui

第3章 系统分析 5 3.1 需求分析 5 3.2 系统可行性分析 5 3.2.1技术可行性&#xff1a;技术背景 5 3.2.2经济可行性 6 3.2.3操作可行性&#xff1a; 6 3.3 项目设计目标与原则 6 3.4系统流程分析 7 3.4.1操作流程 7 3.4.2添加信息流程 8 3.4.3删除信息流程 9 第4章 系统设计 11 …

linux-定时任务

目录 一、crond命令 1、什么是计划任务 2、crond服务的概念 3、crontab 二、at命令 1、at任务的概念 三、邮件服务 1、概念 2、启动postfix 四、mailx命令 1、三个概念&#xff1a; 2、交互式发邮件 3、非交互式发邮件 四、cron定时任务实践 1、系统定时任务配置…

【HUAWEI】单臂路由

目录 ​ &#x1f96e;写在前面 &#x1f96e;2.1、拓扑图 &#x1f96e;2.2、操作思路 &#x1f96e;2.3、配置操作 &#x1f363;2.3.1、LSW4配置 &#x1f363;2.3.2、R2配置 &#x1f363;2.3.3、测试网络 &#x1f990;博客主页&#xff1a;大虾好吃吗的博客 &…

Cruise 从零搭建模型

第一步&#xff0c;新建一个project&#xff1a; 下面添加version&#xff1a; 将该新建的task加载进来&#xff0c;然后保存&#xff1a; 保存完之后&#xff0c;文件夹内多了很多内容&#xff1a; .prj 文件是工程文件。 .bdf 是存放模型里面的数据的文件。 可以看出&#…

ElementUI之首页导航+左侧菜单->mockjs,总线

mockjs总线 1.mockjs 什么是Mock.js 前后端分离开发开发过程当中&#xff0c;经常会遇到以下几个尴尬的场景&#xff1a; - 老大&#xff0c;接口文档还没输出&#xff0c;我的好多活干不下去啊&#xff01; - 后端小哥&#xff0c;接口写好了没&#xff0c;我要测试啊&#x…

springcloud之自我介绍

写在前面 在这篇文章 中我们分析了单体应用的问题&#xff0c;以及用来解决这些问题的解决的方案微服务&#xff0c;并接着看了微服务需要考虑的各种&#xff0c;如服务调用&#xff0c;负载均衡&#xff0c;服务治理&#xff0c;链路追踪&#xff0c;分布式事务&#xff0c;等…

Linux多线程【线程互斥与同步】

✨个人主页&#xff1a; 北 海 &#x1f389;所属专栏&#xff1a; Linux学习之旅 &#x1f383;操作环境&#xff1a; CentOS 7.6 阿里云远程服务器 文章目录 &#x1f307;前言&#x1f3d9;️正文1、资源共享问题1.1、多线程并发访问1.2、临界区与临界资源1.3、“锁” 概念引…

用于自然语言处理的 Python:理解文本数据

一、说明 Python是一种功能强大的编程语言&#xff0c;在自然语言处理&#xff08;NLP&#xff09;领域获得了极大的普及。凭借其丰富的库集&#xff0c;Python 为处理和分析文本数据提供了一个全面的生态系统。在本文中&#xff0c;我们将介绍 Python for NLP 的一些基础知识&…

提升 Windows 生产力的实用工具集:Microsoft PowerToys | 开源日报 No.42

microsoft/PowerToys Stars: 95.2k License: MIT Microsoft PowerToys 是一套用于调整和优化 Windows 体验以提高生产力的实用工具集。该项目包含多个功能模块&#xff0c;其中主要功能有&#xff1a;Always on Top、FancyZones、File Explorer Add-ons 等。其核心优势和关键特…

Java开源工具库使用之Lombok

文章目录 前言一、常用注解1.1 AllArgsConstructor/NoArgsConstructor/RequiredArgsConstructor1.2 Builder1.3 Data1.4 EqualsAndHashCode1.5 Getter/Setter1.6 Slf4j/Log4j/Log4j2/Log1.7 ToString 二、踩坑2.1 Getter/Setter 方法名不一样2.2 Builder 不会生成无参构造方法2…