SpringSecurity学习

SpringSecurity简介

安全框架的概述

什么是安全框架?是为了解决安全问题的框架。如果没有安全框架,我们需要手动处理每个资源的访问控制,非常麻烦。使用安全框架,我们可以通过的配置方式实现对资源的访问控制。

常用的安全框架概述

  1. SpringSecurity:Spring家族的一员,是一个能够为基于Spring的企业应用系统提供声明式的安全访问控制解决方案的安全框架。它提供了一组可以在Spring应用上下文配置的Bean,充分利用Spring IOC、DI(控制反转 Inversion of Control)、DI(依赖注入 Dependency Injection)和AOP(面向切面编程)功能,为应用系统提供声明式的安全访问控制功能,减少了为企业系统安全控制编写大量的代码的重复工作。
  2. Apache Shiro:一个功能强大且易于使用的java安全框架,提供了认证和授权、加密、和会话管理。

概述

Spring Security是一个高度自定义的安全框架。利用 Spring 1oC/Dl和AOP功能,为系统提供了声明式安全访问控制功能,减少了为系统安全而编写大量重复代码的工作。

使用Spring Secruity 的原因有很多,但大部分都是发现了javaEE的 Servlet 规范或 EJB规范中的安全功能缺乏典型企业应用场景。同时认识到他们在 WAR 或 EAR 级别无法移植。因此如果你更换服务品环境,还有大量工作去重新配置你的应用程序。使用 Spring Security解决了这些问题,也为你提供许多其他有用的、可定制的安全功能。

正如你可能知道的两个应用程序的两个主要区域是认证"和"授权”(或者访问控制)。

这两点也是 Spring Security 重要核心功能。

“认证”,是建立一个他声明的主体的过程(一个“主体”—般是指用户,设备或一些可以在你的应用程序中执行动作的其他系统),通俗点说就是系统认为用户是否能登录。

“授权"指确定—个主体是否允许在你的应用程序执行一个动作的过程。通俗点讲就是系统判断用户是否有权限去做某些事情。

源码分析

UserDetailsService

UserDetails

User

可以看到这个user类,这个user类,可不是我们平时定义的user类。这是SpringSecurity中定义的user类。

它最主要的有两个构造函数。

它这个password是我们根据userdetailsService的loadUserByUsername(username) 去数据库中查出来的数据。

是不是很像我们平时开发的逻辑。

具体使用

自定义登录逻辑

在我们使用SpringSecurity做开发的时候,我们其实只有去实现两个接口。

一个是UserDetailsService、另一个就是PasswordEncoder。

自定义username

前面的根据是调用 loadUserByUsername(username) 去数据库查询用户,而要实现登陆的工能,就需要我们来自定义实现,所以就要用到PasswordEncoder接口。用来对用户数的密码加密,同时在和数据库中加过密的密码,来进行匹配。只要匹配成功,就可以实现登陆逻辑。

其实呢我们倒入依赖的时候,它就要实现。在我们的demo中,程序的启动之后控制台会打印一句话。

他的意思就是,自动生成的密码,在demo中我们自定义了,login 方法。

当我们在浏览器中使用login 方法,来实现登录的时候我们会发现。莫名其妙的弹出来一个login界面。我还以为是我自己写的。一想我咋可能写出这么好看的登录界面。确定的是,这肯定不是我自己写的。

所以呢,这就是SpringSecurity中自带的登录页面,目的就是为了,对用户进行拦截和认证。只要登录的用户才会被授权,进行后续的操作。

它规定的username,就是user,密码就是控制台打印的。

那倒我们要拿着玩意实现我们的登录逻辑嘛,显然是不可能。所以我们要再次基础上自定义我们的登录逻辑。

首先,我们肯定要重写 UserDetailsService 的 loadUserByUsername(username)的方法,为什么呢?

显然不同的用户有不同的username,所赋予的权限也不同。肯定需要重写。

接下来,我们平时的登录业务,大体上都是根据username,去数据库查询,查询到了返回整个对象实体,然后在根据前端用户输入的密码,和数据库查询带过来的对象实体中的密码,进行匹配。

可是,我们也看到,它这个密码显然是加过密了,所以呢,我们也需要对前端传过来的密码,也要进行一个加密,在和数据库中的密码进行匹配。当然了,在真实的开发,数据库当然是不会存明文密码,你懂的。

自定义登录密码

所以呢,我也需要实现这个PasswordEncoder接口。对我们用户输入的密码,进行加密。然后在登录的业务中,进行匹配。

那接下来,我们就看看这个接口。

常用的也就是,加密和匹配。它这个加密是不可逆的。

那我们简单的把玩一下这个 BCryptPasswordEncoder

@SpringBootTest
public class PasswordEncoder_test {@Testpublic void test(){BCryptPasswordEncoder bc = new BCryptPasswordEncoder();//对原始的密码进行加密String encode = bc.encode("123");System.out.println(encode);//原始密码和加过密的进行匹配boolean matches = bc.matches("123", encode);System.out.println(matches);}
}//测试结果
$2a$10$cl18e/WgokCZsHpvdJWHbO7QOcDxZUWMVn5JtSAdIObpZ08JUs8XW
true

但是在我们的平常使用中springSecurity要求我们在spring的容器中有一个实例,所以我们平时都会一个配置类。配合@Configuration注解。@Bean注解。

在这里,我们拓展一下。使用SpringBoot做开发的同学。对下面的这个配置类,不少见吧。可是你真的知道这两个注解的作用吗?

@Configuration注解,就像当于我们在用Spring开发写的xml配置文件的作用。而@Bean就相当于我们在xml中写的标签。@Bean注解作用在方法上,声明当前方法的返回值是一个Bean。

package com.uin.config;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;/*** @author wanglufei* @description: SpringSecurity配置类* @date 2022/4/10/7:51 PM*/
@Configuration
public class SpringSecurityConfig{/*** BCryptPasswordEncoder实例** @return org.springframework.security.crypto.password.PasswordEncoder* @author wanglufei* @date 2022/4/11 8:32 AM*/@Beanpublic PasswordEncoder passwordEncoder() {return new BCryptPasswordEncoder();}
}

自定义登录。

package com.uin.service.impl;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.authority.AuthorityUtils;
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.Service;/*** @author wanglufei* @description: 实现SpringSecurity中的UserDetailsService* @date 2022/4/11/8:43 AM*/
@Service
public class UserDetailsServiceImpl implements UserDetailsService {@AutowiredPasswordEncoder passwordEncoder;/*** 自定义username** @param username* @return org.springframework.security.core.userdetails.UserDetails* @author wanglufei* @date 2022/4/11 8:44 AM*/@Overridepublic UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {//1.根据username去查询数据库,不存在的就会抛出异常UsernameNotFoundExceptionif (!"admin".equals(username)) {return (UserDetails) new UsernameNotFoundException("用户名不存在");}//2.把查询的密码(注册是已经加过密)进行解析,或者直接把密码放入构造方法String password = passwordEncoder.encode("123");return new User(username, password, AuthorityUtils.commaSeparatedStringToAuthorityList("admin,normal"));}
}

我们会发现控制台并没有,打印刚才自动生成的密码,

发现是可以登录的。

当然自定义登录逻辑,远远不止于此。

自定义登录页面

我们不可能,一直用它这个登录页面吧,所以我们需要自定义登录页面。在SpringSecurity中有一个这样的类,提供我们做一些自定义的配置。

记得把super.configure(http)。这个是默认的配置。

页面太丑,反正实现效果了。

但是我们会发现一个问题,我们不登陆也可以访问main.html。这不就bbq了。所以我们要拦截请求。

但是在SpringSecurity里,它就做授权,授于你权利,让你去那个页面,就很像我们的在SSM中配置的拦截器。所以我们要转换一下概念,入乡随俗嘛。

这个就起到了,拦截器的作用。

哇涩,重定向次数过多。想了一下,好像我们去访问login.html页面也被拦截了,有点想一个死递归,死循环。

自定义登录失败跳转页面

自定义登录参数

工作流程

spring security 入门教程 详细讲解 - Caesar_the_great - 博客园 (cnblogs.com)

认证流程(authentication)

授权流程(authorization)

优点

  1. 将用户登录,权限控制分离出来,达到和其他控制、逻辑代码完全分离。
  2. 在控制、逻辑代码里面,可以通过spring容器的到我们登录用户的信息,可插拔性的体现。
  3. 自定义的权限控制访问,不但是对某个URL可操控,同时可以对某个方法进行控制。
  4. 提供一些登录相关的操作,如记住我、登录成功跳转页面设定等等。
  5. 安全控制性好,对并发session可控性好。

实现匿名访问

spring security 实现匿名访问 - Caesar_the_great - 博客园 (cnblogs.com)

思路

  1. 标注需要匿名访问的接口
  2. 配置匿名访问

实例

自定义注解 @AnonymousAccess,写在需要匿名访问的接口上:

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface AnonymousAccess {
}
/*** 功能描述: 登录* @param loginVO 用户登录时的账号和密码* @Description TODO* @return com.rman.iflash.model.R* @Author Caesar* @Date 10:57 2020/5/3**/@AnonymousAccess@PostMapping("/login")public R login(@RequestBody @Validated LoginVO loginVO){log.info("用户登录信息{}", loginVO);LoginVO authUserDTO = new LoginVO();authUserDTO.setUsername(loginVO.getUsername());authUserDTO.setPassword(loginVO.getPassword());authUserDTO.setCaptchaId(loginVO.getCaptchaId());authUserDTO.setCaptchaCode(loginVO.getCaptchaCode());Object data = loginService.login(authUserDTO);return R.success(data);}

在security的配置类的 configure(HttpSecurity http)方法中配置匿名访问:

//查找匿名标记URLMap<RequestMappingInfo, HandlerMethod> handlerMethods =applicationContext.getBean(RequestMappingHandlerMapping.class).getHandlerMethods();Set<String> anonymousUrls = new HashSet<>();for (Map.Entry<RequestMappingInfo, HandlerMethod> infoEntry : handlerMethods.entrySet()) {HandlerMethod handlerMethod = infoEntry.getValue();AnonymousAccess anonymousAccess = handlerMethod.getMethodAnnotation(AnonymousAccess.class);if (anonymousAccess != null) {anonymousUrls.addAll(infoEntry.getKey().getPatternsCondition().getPatterns());}}anonymousUrls.forEach(s -> log.warn("可以匿名访问的url:{}", s));http.antMatchers(anonymousUrls.toArray(new String[0])).anonymous()

深入浅出SpringSecurity相关推荐

  1. 我的爬虫都爬出了些什么?

    电机学第七版乌曼课后答案 电化学方法原理和应用第二版邵元华课后答案 电力系统继电保护黄少锋课后答案 生物化学第4版同步辅导与习题集朱圣庚PDF 机床数控技术及应用第四版陈蔚芳课后答案 机器视觉算法与应 ...

  2. 我写了一套SpringBoot+SpringSecurity+Vue权限系统 实战课程,免费分享给CSDN的朋友们

    大家好,我是锋哥,最近写了一套前后端分离的权限系统,逼格略高,专门为Java初学者提升技术层次和方便就业而精心打造.希望你们喜欢!(文末领取) 一,Java就业实战课程简介: 本课程采用主流的技术栈实 ...

  3. SpringSecurity安全验证中文乱码问题

    使用SpringSecurity做安全验证时发现form表单中提交中文名会出现乱码问题. 原因是因为我在web.xml配置文件中将springSecurityFilterChain拦截器放在了 cha ...

  4. Python --深入浅出Apriori关联分析算法(二) Apriori关联规则实战

    上一篇我们讲了关联分析的几个概念,支持度,置信度,提升度.以及如何利用Apriori算法高效地根据物品的支持度找出所有物品的频繁项集. Python --深入浅出Apriori关联分析算法(一) 这次 ...

  5. MSDN Webcast“深入浅出ASP.NET AJAX系列”

    课程: ASP.NET AJAX深入浅出系列课程(1):ASP.NET AJAX 概述(3月13日):对于ASP.NET AJAX的大致功能进行概述和演示,通过简单的演示让听众了解到ASP.NET A ...

  6. 5.3Role和Claims授权「深入浅出ASP.NET Core系列」

    5.3Role和Claims授权「深入浅出ASP.NET Core系列」 原文:5.3Role和Claims授权「深入浅出ASP.NET Core系列」 希望给你3-5分钟的碎片化学习,可能是坐地铁. ...

  7. Spring源码分析【8】-分布式环境SpringSecurity保持用户会话

    1.SpringSecurity的权限控制流程是这样的: 用户登录,基础信息UserInfo存在SpringSecurity的ThreadLocal里. 下面是contextHolder对象: fin ...

  8. SpringSecurity学习:1(第一个SpringSecurity项目)

    此博客是记录自己学习过程的记录 第一个SpringSecurity项目 导入依赖 详细的步骤我就不多说了,使用IDEA创建过SpringBoot项目的人一般都能看懂. 这一步我们可以在使用IDEA创建 ...

  9. Java项目:在线淘房系统(租房、购房)(java+SpringBoot+Redis+MySQL+Vue+SpringSecurity+JWT+ElasticSearch+WebSocket)

    源码获取:博客首页 "资源" 里下载! 该系统有三个角色,分别是:普通用户.房屋中介.管理员.普通用户的功能:浏览房屋信息.预约看房.和中介聊天.申请成为中介等等.房屋中介的功能: ...

  10. SpringSecurity使用 配置文件 和wen.xml 文件配置

    目录 1.web.xml 文件配置 2.spring-security  普通 为使用自己创建的认证类 1.web.xml 文件配置 !-- 配置SpringSecurity的拦截器 -->&l ...

最新文章

  1. 我的华为P30pro手机升级了鸿蒙系统!
  2. js java socket_js使用WebSocket,java使用WebSocket
  3. mixin network_基于Mixin Network的Go语言比特币开发教程 : 用 Mixin Messenger 机器人接受和发送比特币...
  4. mysql过滤器_MYSQL复制过滤器
  5. TCC分布式实现原理及分布式应用如何保证高可用
  6. (23)css3文字阴影text-shadow
  7. oracle date 隐式转换,PL/SQL中的数据类型隐式转换规则
  8. oracle游标fetch_SQL游标@@ FETCH_STATUS函数概述
  9. 125条常见的java面试笔试题大汇总2
  10. 机器学习算法-10贝叶斯信念网络、聚类算法、基于密度的方法DBSCAN
  11. Spring整合log4j日志组件(转)
  12. UDS协议入门之10服务
  13. 数字电路:数据选择器与译码器
  14. 画出属于你的最漂亮的数字时序图—WaveDrom
  15. 【QT小记】设置窗口背景透明
  16. 笔记本加固态小白怎么设置
  17. PL/0 语言简介、PL/0 文法
  18. matlab与maple互联,Maple与Matlab
  19. [Chaosblade] chaosblade-jvm-exec和chaosblade交互
  20. 物联网打破传统行业的枷锁,加速传统行业智能化!

热门文章

  1. 服务器外置硬盘安装教程,小容量Mac用户必看——苹果电脑外接硬盘安装windows教程...
  2. Java小游戏的音乐播放
  3. Javacv录制视频
  4. jQuery 下载与安装教程
  5. TCP/IP协议详解(干货!)
  6. TCPIP详解 IP路由选择
  7. 基于C语言实现的遗传算法系统
  8. Java JSch 远程执行 Shell 命令
  9. Linux 卸载JDK以及安装步骤
  10. 高等代数——大学高等代数课程创新教材(丘维声)——3.1笔记+习题