阶段十-springsecurity总结

jwt认证流程

SpringSecurity 认证过程

 

 

第一步:

创建一个类实现UserDetailsService接口,重写其中的方法

通过重写 public UserDetails loadUserByUsername(String username) 方法

从数据库校验用户输入的用户名

配置SecurityConfig

@Bean注入  PasswordEncoder  通过BCryptPasswordEncoder();

@Bean注入 DaoAuthenticationProvider

设置setUserDetailsService(userDetailsService); 走我们的UsersDetailsService

setPasswordEncoder(passwordEncoder());走我们注入的密码加密器

第二步:

注入过滤器链 SecurityFilterChain

注入过滤器链忽略资源 WebSecurityCustomizer

@Configuration
public class SecurityConfig {@Autowiredprivate UserDetailsService userDetailsService;@Beanpublic PasswordEncoder passwordEncoder(){return new BCryptPasswordEncoder();}//注入UserDetailsService@Beanpublic DaoAuthenticationProvider authenticationProvider(){DaoAuthenticationProvider auth = new DaoAuthenticationProvider();auth.setUserDetailsService(userDetailsService);auth.setPasswordEncoder(passwordEncoder());return auth;}//注入认证管理器@Beanpublic AuthenticationManager authenticationManager(AuthenticationConfiguration authenticationConfiguration) throws Exception {return authenticationConfiguration.getAuthenticationManager();}//注入过滤连@Beanpublic SecurityFilterChain filterChain(HttpSecurity http) throws Exception {//关闭csrf攻击防护http.csrf().disable();//配置认证请求,所有请求都需要过滤http.authorizeRequests().anyRequest().authenticated();//关闭session会话http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);return http.build();}//注入过滤链忽略资源@Beanpublic WebSecurityCustomizer securityCustomizer() throws Exception{return (web )->{web.ignoring().antMatchers("/user/login");};}
}

第三步:

登录实现类

 //认证管理器完成认证UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(user.getUsername(),user.getPassword());Authentication authenticate = authenticationManager.authenticate(authenticationToken);if(Objects.isNull(authenticate)){throw new RuntimeException("用户名或密码错误");}//使用userid生成tokenUser loginUser = (User) authenticate.getPrincipal();String userId = loginUser.getId().toString();String token = jwtUtils.generateToken(userId);//authenticate存入redisstringRedisTemplate.opsForValue().set("login:"+userId, JSON.toJSONString(loginUser));//把token响应给前端HashMap<String,String> map = new HashMap<>();map.put("token",token);return new ResponseResult(200,"登陆成功",map);

第四步:

自己定义认证管理器jwtAuthenticationTokenFilter

最后把读取到的数据存入本地线程中

为什么放行,因为放行之后有人处理

@Component
public class JwtAuthenticationTokenFilter extends OncePerRequestFilter {@Autowiredprivate StringRedisTemplate stringRedisTemplate;@Autowiredprivate JwtUtils jwtUtils;@Overrideprotected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {//获取tokenString token = request.getHeader("token");if (!StringUtils.hasText(token)) {//放行filterChain.doFilter(request, response);//防止过滤链执行完在执行过滤器。return;}//解析tokenString userId;try {userId = jwtUtils.getUserIdFromToken(token);} catch (Exception e) {e.printStackTrace();throw new RuntimeException("token非法");}//从redis中获取用户信息String redisKey = "login:" + userId;String json = stringRedisTemplate.opsForValue().get(redisKey);User loginUser = JSONObject.parseObject(json, User.class);if (Objects.isNull(loginUser)) {throw new RuntimeException("用户未登录");}//将用户信息存入SecurityContextHolder中//TODO 获取权限信息封装到Authenication中UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken =new UsernamePasswordAuthenticationToken(loginUser,null,null);SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken);//放行filterChain.doFilter(request,response);}
}

把我们的过滤器放入过滤器链

//配置认证过滤器http.addFilterAfter(jwtAuthenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);

因为jwtAuthenticationTokenFilter继承OncePerRequestFilter

为防止SpringBoot的FilterRegistrationBean执行OncePerRequestFilter过滤器

@Configuration
public class WebConfig {@Beanpublic FilterRegistrationBean filterRegistrationBean(JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter){FilterRegistrationBean<Filter> filterFilterRegistrationBean = new FilterRegistrationBean<>(jwtAuthenticationTokenFilter);filterFilterRegistrationBean.setEnabled(false);return filterFilterRegistrationBean;}
}

第五步:退出登录

从本地线程中获取数据,直接删除,最彻底的是前后端都删除

授权

在springsecurity配置类中开启注解

@EnableWebSecurity //开启springSecurity框架
@EnableGlobalMethodSecurity(prePostEnabled = true)//开启权限注解开发

在controller上配置权限注解

例如:

@PreAuthorize("hasAuthority('test')")
封装权限信息

注意实体类中的权限信息,两个集合

 /** 用户拥有权限* */@TableField(exist = false)private Collection<String> menus;@Override@JSONField(serialize = false)public Collection<? extends GrantedAuthority> getAuthorities() {Collection<GrantedAuthority> collection = new ArrayList();for (String str : menus){SimpleGrantedAuthority simpleGrantedAuthority = new SimpleGrantedAuthority(str);collection.add(simpleGrantedAuthority);}return collection;}

在UserDetailServiceImpl中加入权限,从数据库中获取(多表连接),这里是写死的

//返回user自动会和前台接收的密码比对,这里不用比对密码Collection<String> collection = new ArrayList<>();collection.add("test");user.setMenus(collection);return user;

认证过滤器解析权限数据也加入权限信息

//将用户信息存入SecurityContextHolder中// 获取权限信息封装到Authenication中UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken =new UsernamePasswordAuthenticationToken(loginUser,null,loginUser.getAuthorities());

自定义失败处理

如果是认证过程中出现的异常会被封装成AuthenticationException然后调用AuthenticationEntryPoint对象的方法去进行异常处理。

如果是授权过程中出现的异常会被封装成AccessDeniedException然后调用AccessDeniedHandler对象的方法去进行异常处理。

在SpringSecurity配置信息中注入

    @Autowiredprivate AuthenticationEntryPoint authenticationEntryPoint;@Autowiredprivate AccessDeniedHandler accessDeniedHandler;
 http.exceptionHandling().authenticationEntryPoint(authenticationEntryPoint).accessDeniedHandler(accessDeniedHandler);

跨域问题解决

@Configuration
public class CorsConfig implements WebMvcConfigurer {@Overridepublic void addCorsMappings(CorsRegistry registry) {// 设置允许跨域的路径registry.addMapping("/**")// 设置允许跨域请求的域名.allowedOrigins("*")// 是否允许cookie.allowCredentials(true)// 设置允许的请求方式.allowedMethods("GET", "POST", "DELETE", "PUT")// 设置允许的header属性.allowedHeaders("*")// 跨域允许时间.maxAge(3600);}
}

开启SpringSecurity的跨域访问

    @Overrideprotected void configure(HttpSecurity http) throws Exception {...//允许跨域http.cors();}

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

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

相关文章

node.js mongoose aggregate

目录 官方文档 简述 Aggregate的原型方法 aggregate进行操作 官方文档 Mongoose v8.0.3: Aggregate 简述 在 Mongoose 中&#xff0c;Aggregate 是用于执行 MongoDB 聚合操作的类。MongoDB 聚合操作是一种强大的数据处理工具&#xff0c;可以用于对集合中的文档进行变换和…

1.【分布式】分布式事务详解

分布式事务 1.分布式事务是什么&#xff1f;数据库事务 2.分布式事务产生的原因&#xff1f;存储层拆分服务层拆分 3.分布式事务解决方案4.分布式事务有哪些开源组件SeateTCC 分布式服务组件基于消息补偿的最终一致性 5.两阶段提交&#xff0c;三阶段协议详解二阶段提交协议三阶…

单片机应用实例:LED显示电脑电子钟

本例介绍一种用LED制作的电脑电子钟&#xff08;电脑万年历&#xff09;。其制作完成装潢后的照片如下图&#xff1a; 上图中&#xff0c;年、月、日及时间选用的是1.2寸共阳数码管&#xff0c;星期选用的是2.3寸数码管&#xff0c;温度选用的是0.5寸数码管&#xff0c;也可根据…

文件操作(下)

标题的顺序是接着之前写的&#xff0c;希望这篇博客对你有帮助 七. 随机读写函数 实际上&#xff0c;无论是读还是写&#xff0c;在一次调用顺序读写函数&#xff0c;文件指针会移到已经读过或者写过的下一个位置&#xff0c;从那个位置开始下一次读和写&#xff08;在文件没有…

Ansible常用模块详解(附各模块应用实例和Ansible环境安装部署)

目录 一、ansible概述 1、简介 2、Ansible主要功能&#xff1a; 3、Ansible的另一个特点&#xff1a;所有模块都是幂等性 4、Ansible的优点&#xff1a; 5、Ansible的四大组件&#xff1a; 二、ansible环境部署&#xff1a; 1、环境&#xff1a; 2、安装ansible&#…

QT Widget - 随便画个圆

简介 实现在界面中画一个圆, 其实目的是想画一个LED效果的圆。代码 #include <QApplication> #include <QWidget> #include <QPainter> #include <QColor> #include <QPen>class LEDWidget : public QWidget { public:LEDWidget(QWidget *pare…

WPF仿网易云搭建笔记(7):HandyControl重构

文章目录 专栏和Gitee仓库前言相关文章 新建项目项目环境项目结构 代码结果结尾 专栏和Gitee仓库 WPF仿网易云 Gitee仓库 WPF仿网易云 CSDN博客专栏 前言 最近我发现Material Design UI的功能比较简单&#xff0c;想实现一些比较简单的功能&#xff0c;比如消息提示&#xff0…

智能物联网汽车3d虚拟漫游展示增强消费者对品牌的认同感和归属感

汽车3D虚拟展示系统是一种基于web3D开发建模和VR虚拟现实技术制作的360度立体化三维汽车全景展示。它通过计算机1:1模拟真实的汽车外观、内饰和驾驶体验&#xff0c;让消费者在购车前就能够更加深入地了解车辆的性能、特点和设计风格。 华锐视点云展平台是一个专业的三维虚拟展…

音乐制作软件Studio One mac软件特点

Studio One mac是一款专业的音乐制作软件&#xff0c;由美国PreSonus公司开发。该软件提供了全面的音频编辑和混音功能&#xff0c;包括录制、编曲、合成、采样等多种工具&#xff0c;可用于制作各种类型的音乐&#xff0c;如流行音乐、电子音乐、摇滚乐等。 Studio One mac软件…

Elasticsearch 索引生命周期和翻滚 (rollover) 策略

Elasticsearch 是搜索引擎中的摇滚明星&#xff0c;它的蓬勃发展在于使你的数据井井有条且速度快如闪电。 但当你的数据成为一场摇滚音乐会时&#xff0c;管理其生命周期就变得至关重要。 正确使用索引生命周期管理 (ILM) 和 rollover 策略&#xff0c;你的后台工作人员可确保顺…

[Toolschain cpp ros cmakelist python vscode] 记录写每次项目重复的设置和配置 不断更新

写在前面 用以前的设置&#xff0c;快速配置项目&#xff0c;以防长久不用忘记&#xff0c;部分资料在资源文件里还没有整理 outline cmakelist 复用vscode 找到头文件vscode debug现有代码直接关联远端gitros杂记repo 杂记glog杂记 cmakelist 复用 包含了根据系统路径找库…

龙迅LT6211B,HDMI1.4转LVDS,应用于AR/VR市场

产品描述 LT6211B 是一款用于 VR/ 显示应用的高性能 HDMI1.4 至 LVDS 芯片。 对于 LVDS 输出&#xff0c;LT6211B 可配置为单端口、双端口或四端口。对于2D视频流&#xff0c;同一视频流可以映射到两个单独的面板&#xff0c;对于3D视频格式&#xff0c;左侧数据可以发送到一个…

深入理解 HTTP 和 HTTPS:提升你的网站安全性(下)

&#x1f90d; 前端开发工程师&#xff08;主业&#xff09;、技术博主&#xff08;副业&#xff09;、已过CET6 &#x1f368; 阿珊和她的猫_CSDN个人主页 &#x1f560; 牛客高级专题作者、在牛客打造高质量专栏《前端面试必备》 &#x1f35a; 蓝桥云课签约作者、已在蓝桥云…

PowerQuery:不会直接访问数据源,请重新生成此数据组合

报错信息&#xff1a; ⚠️ Formula.Firewall: 查询“到货表_已有数据”(步骤“删除的其他列”) 将引用其他查询或步骤&#xff0c;因此可能不会直接访问数据源。请重新生成此数据组合。 查询“”将引用其他查询或步骤&#xff0c;因此可能不会直接访问数据源&#xff0c;请重…

YOLOv8改进 | 主干篇 | 轻量级网络ShuffleNetV1(附代码+修改教程)

一、本文内容 本文给大家带来的改进内容是ShuffleNetV1&#xff0c;这是一种为移动设备设计的高效CNN架构。它通过使用点群卷积和通道混洗等操作&#xff0c;减少了计算成本&#xff0c;同时保持了准确性&#xff0c;通过这些技术&#xff0c;ShuffleNet在降低计算复杂度的同时…

Chromadb词向量数据库总结

简介 Chroma 词向量数据库是一个用于自然语言处理&#xff08;NLP&#xff09;和机器学习的工具&#xff0c;它主要用于词嵌入&#xff08;word embeddings&#xff09;。词向量是将单词转换为向量表示的技术&#xff0c;可以捕获单词之间的语义和语法关系&#xff0c;使得计算…

如何储存白葡萄酒和如何储存红葡萄酒?

为了进一步帮助软木塞在葡萄酒储存过程中正常工作&#xff0c;考虑一下他们储存区域的湿度水平。来自云仓酒庄品牌雷盛红酒分享根据你所处的气候&#xff0c;你的储存区域可能会比你的软木塞想要的要干燥。最佳的葡萄酒储存湿度条件在50-70%之间。此外&#xff0c;如果您的存储…

whisper深入-语者分离

文章目录 学习目标&#xff1a;如何使用whisper学习内容一&#xff1a;whisper 转文字1.1 使用whisper.load_model()方法下载&#xff0c;加载1.2 使用实例对文件进行转录1.3 实战 学习内容二&#xff1a;语者分离&#xff08;pyannote.audio&#xff09;pyannote.audio是huggi…

nextjs + sharp在 vercel 环境svg转png出现中文乱码

在之前一篇博客 Next.js和sharp实现占位图片生成工具&#xff0c;详细介绍了使用 Next.js sharp Vercel 来实现一个 占位图片生成工具&#xff0c;遇到一个奇怪的问题&#xff1a;在本地开发环境&#xff0c;英文、数字、中文字符自定义内容&#xff0c;都能正常渲染。但是发…

IP地址段与子网掩码对应表,网工人手一份!

你们好&#xff0c;我的网工朋友。 IP地址的设置与子网掩码的使用是网络中最容易出错的地方之一&#xff0c;很多项目之所有故障不断&#xff0c;原因皆在于此。 不少网工朋友也经常在群里讨论过这个问题&#xff0c;之前公众号也分享过相关内容&#xff0c;可以看看这篇&…