SpringSecurity的使用

文章目录

  • 原理
  • 使用
    • 自定义权限校验
  • 主要类
    • 通过debug的方式查看security有哪些过滤器
    • 配置类
    • UsernamePasswordAuthenticationFilter
    • UserDetailsService
    • ExceptionTranslationFilter
      • 自定义认证和授权异常处理
    • FilterSecurityInterceptor权限校验
      • 创建拦截器获取用户权限并传递给security
      • 创建controller使用注解添加权限认证
    • WebSecurityConfigurerAdapter
    • BCryptPasswordEncoder
    • UserDetails
    • AuthenticationEntryPoint
    • JWT实现认证授权

原理

SpringSecurity的原理其实就是一个过滤器链,内部包含了提供各种功能的过滤器,

使用

需要的依赖

<parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.5.4</version>
</parent><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-security</artifactId></dependency></dependencies>

自定义权限校验

在需要校验的方法上添加此注解
@PreAuthorize(“@ex.hasAuthority(‘ROLE_ADMIN’)”)
ex为自定义的类的别名,
hasAuthority为自定义校验权限的方法

自定义的类方法

@Service("ex")
public class CustomAuthority {public boolean hasAuthority(String authority) {// 获取当前用户的所有权限// 判断用户权限集合中是否包含authorityreturn true; // 模拟有权限}
}

主要类

通过debug的方式查看security有哪些过滤器

在这里插入图片描述

配置类

package org.example.config;import org.example.filter.JWTAuthenticationTokenFilter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
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.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.security.web.access.AccessDeniedHandler;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {@Autowiredprivate AuthenticationEntryPoint authenticationEntryPoint;@Autowiredprivate AccessDeniedHandler accessDeniedHandler;@Beanpublic PasswordEncoder passwordEncoder(){return new BCryptPasswordEncoder();}@Overrideprotected void configure(HttpSecurity http) throws Exception {String[] urls = {"/user/login",}; // 需要放行的地址http.csrf().disable() // 关闭csrf.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and() // 每次调用and都会返回一个新的HttpSecurity并可以再次调用HttpSecurity对象的方法.authorizeRequests().antMatchers(urls).anonymous() // 可以匿名访问的地址.antMatchers("/user/login").permitAll() // 允许所有用户都有权限访问.anyRequest().authenticated(); // 除可以匿名访问的地址外,其他地址都要认证// 添加过滤器,第一个参数是要添加的过滤器,第二个参数是要添加在哪个过滤器之前,第二个参数必须是security已经管理的过滤器http.addFilterBefore(new JWTAuthenticationTokenFilter(), UsernamePasswordAuthenticationFilter.class);// 设置认证和授权异常处理http.exceptionHandling().authenticationEntryPoint(authenticationEntryPoint).accessDeniedHandler(accessDeniedHandler);}@Bean@Overridepublic AuthenticationManager authenticationManagerBean() throws Exception {return super.authenticationManagerBean();}
}

UsernamePasswordAuthenticationFilter

负责我们在登录页面填写了用户密码后的登录请求

UserDetailsService

可以通过此接口的loadUserByUsername方法实现自定义的用户认证

package org.example.service;import org.example.domain.LoginUser;
import org.example.domain.User;
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.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;@Service
public class UserDetailServiceImpl implements UserDetailsService {@Autowiredprivate PasswordEncoder passwordEncoder;@Overridepublic UserDetails loadUserByUsername(String userName) throws UsernameNotFoundException {// 查询用户信息并,此处模拟查询的用户信息User user = new User();user.setUserName("test");BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
//        user.setPassword("{noop}123"); // {noop}是为了不用给密码加密,后面跟的是密码user.setPassword(passwordEncoder.encode("123"));// 查询权限信息,此处模拟return new LoginUser(user);}
}

ExceptionTranslationFilter

处理过滤器链中抛出任何AccessDeniedException和AuthenticationException

自定义认证和授权异常处理

我们希望在认证失败或者授权失败的情况下和业务代码一样返回相同的数据结构,这样可以让前端对响应进行统一的处理。
在springsecurity中,如果我们在认证或者授权的过程中出现了异常的会被ExceptionTranslationFilter捕获到,在ExceptionTranslationFilter中会判断是认证失败还是授权失败出现的异常。
如果认证过程中出翔异常会被封装成AuthenticationException然后调用AuthenticationEntryPoint对象的方法进行异常处理。
如果是授权过程中出现了异常会被封装成AccessDeniedException然后调用AccessDeniedHandler对象的方法进行异常处理。
所以如果我们需要自定义异常处理,我们只需要自定义AuthenticationEntryPoint和AccessDeniedHandler然后配置被springsecurity即可

AuthenticationEntryPoint

package org.example.handler;import org.example.util.WebUtil;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.stereotype.Service;import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;@Service
public class AuthenticationEntryPointImpl implements AuthenticationEntryPoint {@Overridepublic void commence(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AuthenticationException e) throws IOException, ServletException {e.printStackTrace();WebUtil.renderString(httpServletResponse, "认证异常");}
}

AccessDeniedHandler

package org.example.handler;import org.example.util.WebUtil;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.web.access.AccessDeniedHandler;
import org.springframework.stereotype.Service;import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;@Service
public class AccessDeniedHandlerImpl implements AccessDeniedHandler {@Overridepublic void handle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AccessDeniedException e) throws IOException, ServletException {e.printStackTrace();WebUtil.renderString(httpServletResponse, "没有权限");}
}

WebUtil

package org.example.util;import javax.servlet.http.HttpServletResponse;public class WebUtil {public static void renderString(HttpServletResponse response, String responseStr) {response.setStatus(200);response.setContentType("application/json");response.setCharacterEncoding("utf-8");try {response.getWriter().print(responseStr);} catch (Exception e) {e.printStackTrace();}}
}

FilterSecurityInterceptor权限校验

需要现在配置类上先开启权限校验配置
使用@EnableGlobalMethodSecurity(prePostEnabled = true)
再在需要权限校验的方法上使用注解
负责权限校验的过滤器,认证时会通过SecurityContextHolder.getContext().setAuthentication(authenticationToken);保存用户不权限集合

创建拦截器获取用户权限并传递给security

package org.example.filter;import org.example.domain.LoginUser;
import org.example.domain.User;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
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.Arrays;public class JWTAuthenticationTokenFilter extends OncePerRequestFilter {@Overrideprotected void doFilterInternal(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, FilterChain filterChain) throws ServletException, IOException {// 伪代码// 获取token// 解析token// 获取用户信息,此处模拟获取用户信息LoginUser loginUser = new LoginUser();User user = new User();user.setUserName("test");BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
//        user.setPassword("{noop}123"); // {noop}是为了不用给密码加密,后面跟的是密码user.setPassword(passwordEncoder.encode("123"));loginUser.setUser(user);loginUser.setPermissions(Arrays.asList("admin", "test"));// 此处用三个参数的构造函数,因为用了此函数后不会再走用户登录的认证逻辑// 三个参数的构造函数,第一个参数是登录用户,第二个参数是密码,// 第三个参数是权限集合,当权限校验时security会使用默认的过滤器FilterSecurityInterceptor校验此集合数据UsernamePasswordAuthenticationToken authenticationToken =new UsernamePasswordAuthenticationToken(loginUser, null, loginUser.getAuthorities());
//        SecurityContextHolder// 存入SecurityContextHolder中,用于后续的过滤器使用用户信息SecurityContextHolder.getContext().setAuthentication(authenticationToken);// 放行filterChain.doFilter(httpServletRequest, httpServletResponse);}
}

创建controller使用注解添加权限认证

package org.example.controller;import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
public class HelloController {@GetMapping("/hello")@PreAuthorize("hasAuthority('admin')") // 此是调用的security的hasAuthority方法public String hello() {return "Hello World!";}
}

WebSecurityConfigurerAdapter

配置抽象类,可以通过实现此抽象类,实现里面的protected void configure(HttpSecurity http)方法实现security的自定义配置

BCryptPasswordEncoder

对密码进行加密和匹配

  • encode:对密码进行加密方法
  • matches:对明文密码和加密过的密码进行密码验证

UserDetails

编写用户类实现此接口,用于保存用户信息和鉴权

  • getAuthorities:用于将用户的权限传递给SpringSecurity,将权限字符串封装成SimpleGrantedAuthority并传递给SpringSecurity
package org.example.domain;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;@Data
@AllArgsConstructor
@NoArgsConstructor
public class LoginUser implements UserDetails {/*** 项目中的用户类,用与从数据库中查询保存结果*/private User user;private List<String> permissions; // 权限校验@Overridepublic Collection<? extends GrantedAuthority> getAuthorities() {List<SimpleGrantedAuthority> collect = permissions.stream().map(SimpleGrantedAuthority::new).collect(Collectors.toList());return collect;}@Overridepublic String getPassword() {return user.getPassword();}@Overridepublic String getUsername() {return user.getUserName();}/*** 判断用户是否没过期* @return*/@Overridepublic boolean isAccountNonExpired() {return true;}@Overridepublic boolean isAccountNonLocked() {return true;}@Overridepublic boolean isCredentialsNonExpired() {return true;}@Overridepublic boolean isEnabled() {return true;}
}

AuthenticationEntryPoint

异常处理的接口,实现此接口的方法,将实现类设置到security中,有认证异常会调用实现类的方法

JWT实现认证授权

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

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

第30周:彩色图片分类(Tensorflow实战第二周)

目录 前言 一、前期工作 1.1 设置GPU 1.2 导入数据 1.3 数据归一化 1.4 数据可视化 二、构建CNN网络 2.1 基本概念 2.2 代码实现 三、编译 四、训练模型 五、预测 六、模型评估 总结 前言 &#x1f368; 本文为[&#x1f517;365天深度学习训练营]中的学习记录博…

【Linux】信号

&#x1f308;个人主页&#xff1a;秦jh__https://blog.csdn.net/qinjh_?spm1010.2135.3001.5343&#x1f525; 系列专栏&#xff1a;https://blog.csdn.net/qinjh_/category_12625432.html 目录 信号和信号量 信号 信号的处理 信号捕捉 信号的产生 系统调用 signal rais…

【国内中间件厂商排名及四大中间件对比分析】

国内中间件厂商排名 随着新兴技术的涌入&#xff0c;一批国产中间件厂商破土而出&#xff0c;并在短时间内迅速发展&#xff0c;我国中间件市场迎来洗牌&#xff0c;根据市占率&#xff0c;当前我国中间件厂商排名依次为&#xff1a;东方通、宝兰德、中创股份、金蝶天燕、普元…

【题解】CF2033G

题目 CF2033G 分析 一道很显然是树形dp的题&#xff0c;但非常恶心QwQ。   先不管复杂度&#xff0c;找找递推关系&#xff0c;一种很直接的想法如下&#xff08;我觉得是错误的&#xff09;&#xff1a; d p [ i ] [ k ] m a x ( d p [ f a i ] [ k − 1 ] , d p [ s o …

SpringBoot之定时任务

1. 前言 本篇博客是个人的经验之谈&#xff0c;不是普适的解决方案。阅读本篇博客的朋友&#xff0c;可以参考这里的写法&#xff0c;如有不同的见解和想法&#xff0c;欢迎评论区交流。如果此篇博客对你有帮助&#xff0c;感谢点个赞~ 2. 场景 我们讨论在单体项目&#xff0c…

【日志】力扣58.最后一个单词的长度//14.最长公共前缀//28. 找出字符串中第一个匹配项的下标

2024.11.6 【力扣刷题】 58. 最后一个单词的长度 - 力扣&#xff08;LeetCode&#xff09;https://leetcode.cn/problems/length-of-last-word/?envTypestudy-plan-v2&envIdtop-interview-150 int lengthOfLastWord(char* s) {int count 0;for (int i strlen(s) - 1; i…

智能家居的未来:AI让生活更智能还是更复杂?

内容概要 智能家居的概念源于将各种家居设备连接到互联网&#xff0c;并通过智能技术进行控制和管理。随着人工智能的迅速发展&#xff0c;这一领域也迎来了前所未有的机遇。从早期简单的遥控器到如今可以通过手机应用、语音助手甚至是环境感应进行操作的设备&#xff0c;智能…

1. 初步认识 Java 虚拟机

一、前言 其实一直都想系统性的学习一下 JVM&#xff0c;尝试过很多次&#xff0c;最终没能坚持下来&#xff0c;现在已经工作多年&#xff0c;发现对于 JVM这块知识还是很薄弱&#xff0c;不利于职业长远发展&#xff0c;并且之前掌握的都是一些零散的知识&#xff0c;没能形…

数据结构之二叉树的链式结构——递归的暴力美学

1. 实现链式的二叉树结构 我们之前用顺序表里面数组的底层结构实现了二叉树中堆的结构&#xff0c;但是不是所有的二叉树都具有着堆的性质&#xff0c;所以我们现在需要一个链式结构来描述普遍的二叉树。其底层结构类似一个链表&#xff0c;但是每一个结点由单个区域&#xff…

计算机前沿技术-人工智能算法-大语言模型-最新研究进展-2024-10-31

计算机前沿技术-人工智能算法-大语言模型-最新研究进展-2024-10-31 目录 文章目录 计算机前沿技术-人工智能算法-大语言模型-最新研究进展-2024-10-31目录1. Large Language Models for Manufacturing摘要创新点算法模型实验效果&#xff08;包含重要数据与结论&#xff09;推荐…

利用SpringBoot构建城镇住房保障平台

1系统概述 1.1 研究背景 随着计算机技术的发展以及计算机网络的逐渐普及&#xff0c;互联网成为人们查找信息的重要场所&#xff0c;二十一世纪是信息的时代&#xff0c;所以信息的管理显得特别重要。因此&#xff0c;使用计算机来管理城镇保障性住房管理系统的相关信息成为必然…

【笔记】扩散模型(九):Imagen 理论与实现

论文链接&#xff1a;Photorealistic Text-to-Image Diffusion Models with Deep Language Understanding 非官方实现&#xff1a;lucidrains/imagen-pytorch Imagen 是 Google Research 的文生图工作&#xff0c;这个工作并没有沿用 Stable Diffusion 的架构&#xff0c;而是级…

Windows下载安装Ollama本地运行大模型,新手详细

目录 1. 下载安装Ollama2. 环境配置- 关闭开机自启动&#xff08;可选&#xff09;&#xff1a;- 配置环境变量&#xff08;必须&#xff09;&#xff1a;- 配置端口&#xff08;可选&#xff09;&#xff1a;- 允许浏览器跨域请求&#xff08;可选&#xff09;&#xff1a; 3.…

代码随想录算法训练营Day55 | 图论理论基础、深度优先搜索理论基础、卡玛网 98.所有可达路径、797. 所有可能的路径、广度优先搜索理论基础

目录 图论理论基础 深度优先搜索理论基础 卡玛网 98.所有可达路径 广度优先搜索理论基础 图论理论基础 图论理论基础 | 代码随想录 图的基本概念 图的种类 大体分为有向图和无向图。 图中的边有方向的是有向图&#xff1a; 图中的边没有方向的是无向图&#xff1a; 图…

牛客练习赛131(dp,dfs,bfs,线段树维护等差数列)

文章目录 牛客练习赛131&#xff08;dp&#xff0c;dfs&#xff0c;bfs&#xff0c;线段树维护等差数列&#xff09;A. 小H学语文B. 小H学数学&#xff08;dp、偏移值&#xff09;C. 小H学生物&#xff08;DFS、树上两点间路径的距离&#xff09;D. 小H学历史(BFS)E. 小H学物理…

干货分享篇:Air780EP的硬件设计原理全解析(上)

一、绪论 Air780EP是一款基于移芯EC718P平台设计的LTE Cat 1无线通信模组。支持FDD-LTE/TDD-LTE的4G远距离无线传输技术。另外&#xff0c;模组提供了USB/UART/I2C等通用接口满足IoT行业的各种应用诉求。 二、综述 2.1 型号信息 表格 1&#xff1a;模块型号列表 2.2 主要性能…

Python将Word文档转为PDF

将word转pdf&#xff0c;只能使用办公工具&#xff0c;但是这些工具大都是收费。因此想用python 将word转pdf,发现很好用特此记录下。方法一&#xff1a;使用docx2pdf模块将docx文件转为pdf 要实现这样的功能&#xff0c;需要用到的就是 docx2pdf 这个python第三方库。对于doc…

无惧任天堂的法律威胁:Switch模拟器Ryujinx v1.2.72版发布

此前任天堂向多个提供 Nintendo Switch 模拟器项目发送律师函甚至直接起诉&#xff0c;要求这些项目立即停止更新、删除以及向任天堂提供经济赔偿。其中 Ryujinx 项目已经在 2024 年 10 月 1 日因任天堂的法律威胁而放弃项目&#xff0c;不过很快就有分叉版本出现&#xff0c;这…

JavaWeb——Web入门(6/9)-HTTP协议:协议解析(客户端的 HTTP 协议解析、服务端的 HTTP 协议解析、Web服务器的作用)

目录 概述 客户端的 HTTP 协议解析 服务端的 HTTP 协议解析 Web服务器的作用 概述 了解完 HTTP 协议的请求数据格式以及响应数据格式之后&#xff0c;接下来我们来讲了解 HTTP 协议的解析。 HTTP 协议的解析分为客户端和服务端两个部分&#xff0c;客户端浏览器中内置了解…

操作系统-实验报告单(2)

目录 1 实验目标 2 实验工具 3 实验内容、实验步骤及实验结果 一、自定义操作系统并启动 1. 最简单操作系统的编写并生成镜像文件 2.虚拟机启动操作系统 【思考题&#xff1a;1、仔细阅读helloos.nas&#xff0c;结合操作系统启动过程尝试分析它的作用&#xff1b;2、若…