什么是 SpringSecurity?

Spring Security 是一个能够为基于Spring的企业应用系统提供声明式的安全访问控制解决方案的安全框架。它提供了一组可以在Spring应用上下文中配置的Bean,充分利用了Spring IoC,DI(控制反转Inversion of Control ,DI:Dependency Injection 依赖注入)和AOP(面向切面编程)功能,为应用系统提供声明式的安全访问控制功能,减少了为企业系统安全控制编写大量重复代码的工作。

百度百科地址:https://baike.baidu.com/item/spring%20security/8831652?fr=aladdin

SpringCloud Security 是基于 Spring Security 为基础而开发的,因此我们学习了 SpringSecurity 就可以移植到 SpringCloud Security 了,详见中文社区网:https://www.springcloud.cc/

Security 应用场景

Security 在很多企业中作为后台角色权限框架、授权认证 Oauth2.0 、安全防护(防止跨站点请求)、Session攻击、非常容易融合SpringMVC使用等。

先下载本篇博客代码:https://pan.baidu.com/s/1R0Daoh7Zdw1-DQKrLYAbkw   提取码:pshm

本篇代码例子,主要是一个入门的 demo:有2个角色 admin 和 user,其中 admin 有增删改查权限,user 只有读的权限。通过整合 SpringSecurity 和 SpringBoot 来做权限控制,很多代码目前先写固定,主要是为了方便学习,后续会从数据库中读取。

SpringBoot 版本号:2.2.2.RELEASE,SpringCloud 版本号:Hoxton.SR2

首先,代码结构:

在 pom.xml 里,我们需要增加 security 的依赖和 freemarket 的依赖,主要做一些页面模板:

        <!-- springboot整合freemarker --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-freemarker</artifactId></dependency><!-->spring-boot 整合security --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-security</artifactId></dependency>

然后,templates 目录下的文件都比较简单,使用的是 freemarker 模板,需要提一点的就是 login 文件,用户名和密码是与 security 要求的字段名一致,然后在地址里判断是否有 error 而判断是登录失败,实际项目开发,不应该这样判断,目前是为了学习需要。

然后,WebServerAutoConfiguration 配置类,主要是为了自定义 WEB 服务器参数 可以配置默认错误页面。

package com.study.config;import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
import org.springframework.boot.web.server.ErrorPage;
import org.springframework.boot.web.servlet.server.ConfigurableServletWebServerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpStatus;/*** @author biandan* @description 自定义 WEB 服务器参数 可以配置默认错误页面* @signature 让天下没有难写的代码* @create 2021-05-30 下午 9:28*/
@Configuration
public class WebServerAutoConfiguration {@Beanpublic ConfigurableServletWebServerFactory webServerFactory() {TomcatServletWebServerFactory factory = new TomcatServletWebServerFactory();ErrorPage errorPage400 = new ErrorPage(HttpStatus.BAD_REQUEST, "/error/400");ErrorPage errorPage401 = new ErrorPage(HttpStatus.UNAUTHORIZED, "/error/401");ErrorPage errorPage403 = new ErrorPage(HttpStatus.FORBIDDEN, "/error/403");ErrorPage errorPage404 = new ErrorPage(HttpStatus.NOT_FOUND, "/error/404");ErrorPage errorPage415 = new ErrorPage(HttpStatus.UNSUPPORTED_MEDIA_TYPE, "/error/415");ErrorPage errorPage500 = new ErrorPage(HttpStatus.INTERNAL_SERVER_ERROR, "/error/500");factory.addErrorPages(errorPage400, errorPage401, errorPage403, errorPage404, errorPage415, errorPage500);return factory;}
}

最后,需要讲解配置类:SecurityConfig

package com.study.config;import com.study.handler.MyAuthenticationFailureHandler;
import com.study.handler.MyAuthenticationSuccessHandler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
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.factory.PasswordEncoderFactories;
import org.springframework.security.crypto.password.DelegatingPasswordEncoder;
import org.springframework.security.crypto.password.NoOpPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;/*** @author biandan* @description* @signature 让天下没有难写的代码* @create 2021-05-30 下午 9:38*/
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {@Autowiredprivate MyAuthenticationSuccessHandler successHandler;@Autowiredprivate MyAuthenticationFailureHandler failureHandler;// 配置认证用户信息和权限@Overrideprotected void configure(AuthenticationManagerBuilder auth) throws Exception {// 添加admin账号,拥有增删改查权限auth.inMemoryAuthentication().withUser("admin").password("123").authorities("showUser","addUser","updateUser","deleteUser");// 添加user账号,只有查询权限auth.inMemoryAuthentication().withUser("user").password("456").authorities("showUser");}// 配置拦截请求资源@Overrideprotected void configure(HttpSecurity http) throws Exception {// 如何权限控制 给每一个请求路径 分配一个权限名称 然后账号只要关联该名称,就可以有访问权限http.authorizeRequests()// 配置查询用户权限.antMatchers("/showUser").hasAnyAuthority("showUser").antMatchers("/addUser").hasAnyAuthority("addUser").antMatchers("/updateUser").hasAnyAuthority("updateUser").antMatchers("/deleteUser").hasAnyAuthority("deleteUser").antMatchers("/login").permitAll().antMatchers("/**").fullyAuthenticated().and().formLogin().loginPage("/login").successHandler(successHandler).failureHandler(failureHandler).and().csrf().disable();}/* 不推荐使用这种方式,查看博客:https://blog.csdn.net/alinyua/article/details/80219500@Beanpublic static NoOpPasswordEncoder passwordEncoder() {return (NoOpPasswordEncoder) NoOpPasswordEncoder.getInstance();}*/@Beanpublic static PasswordEncoder passwordEncoder(){DelegatingPasswordEncoder encoder = (DelegatingPasswordEncoder)PasswordEncoderFactories.createDelegatingPasswordEncoder();encoder.setDefaultPasswordEncoderForMatches(NoOpPasswordEncoder.getInstance());return encoder;}}

需要注意的是我们需要增加 PasswordEncoder 的 Bean 注解,如果不增加会报错:

java.lang.IllegalArgumentException: There is no PasswordEncoder mapped for the id "null"

原因是升级为 Security5.0 以上密码支持多种加密方式,我们需要恢复以前的模式,不推荐使用 NoOpPasswordEncoder 而是使用 PasswordEncoder。

我们还要禁用 csrf ,同时因为我们使用的是 FromLogin 的方式,如果不禁掉 csrf,必须在表单里传递 token 才能通过。我们设置登录不拦截,代码如下:

.antMatchers("/login").permitAll()

然后,我们需要增加认证成功处理类:

package com.study.handler;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 biandan* @description 认证成功* @signature 让天下没有难写的代码* @create 2021-05-30 下午 9:43*/
@Component
public class MyAuthenticationSuccessHandler implements AuthenticationSuccessHandler {@Overridepublic void onAuthenticationSuccess(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Authentication authentication) throws IOException, ServletException {String username = httpServletRequest.getParameter("username");System.out.println("认证成功,username="+username);//认证成功后跳转到主页httpServletResponse.sendRedirect("/");}
}

认证失败处理类:

package com.study.handler;import org.springframework.context.annotation.Configuration;
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;/*** @author biandan* @description 认证失败* @signature 让天下没有难写的代码* @create 2021-05-30 下午 9:45*/
@Component
public class MyAuthenticationFailureHandler implements AuthenticationFailureHandler {@Overridepublic void onAuthenticationFailure(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AuthenticationException e) throws IOException, ServletException {String username = httpServletRequest.getParameter("username");System.out.println("认证失败,username="+username);//重定向到登录页面,同时在地址后面增加 error 参数httpServletResponse.sendRedirect("/login?error");}
}

application.yml 配置:

server:port: 80# 将SpringBoot项目作为单实例部署调试时,不需要注册到注册中心
eureka:client:fetch-registry: falseregister-with-eureka: falsespring:application:name: security-server# 配置freemarkerfreemarker:# 设置模板后缀名suffix: .ftl# 设置文档类型content-type: text/html# 设置页面编码格式charset: UTF-8# 设置页面缓存cache: false# 设置ftl文件路径template-loader-path:- classpath:/templates# 设置静态文件路径,js,css等mvc:static-path-pattern: /static/**

OK,启动我们的微服务,浏览器地址输入:http://127.0.0.1/

输入 admin 账号,123密码,登录成功:

admin 有增删改查的权限,因此点击每个按钮都有权限。

然后我们切换到 user 账号,user 账号只有查询的权限,点击增删改提示权限不足。

同时我们查看后台日志:

OK,security 的核心流程我们讲解完毕,后面会讲解如何动态的分配权限。这篇博客仅仅做入门,实际开发不可能写固定用户名和密码、权限到代码里去的。

本篇博客代码:https://pan.baidu.com/s/1R0Daoh7Zdw1-DQKrLYAbkw   提取码:pshm

系列学习安全框架 Security 之第 1 篇 —— 认识 SpringSecurity相关推荐

  1. Hadoop学习笔记—15.HBase框架学习(基础知识篇)

    Hadoop学习笔记-15.HBase框架学习(基础知识篇) HBase是Apache Hadoop的数据库,能够对大型数据提供随机.实时的读写访问.HBase的目标是存储并处理大型的数据.HBase ...

  2. Vue框架里使用Swiper - 安装篇

    Vue框架里使用Swiper npm安装swiper cnpm install swiper 相关阅读 Vue框架里使用Swiper 如何在Vue项目中优雅的使用swiper插件 https://ww ...

  3. Express框架的安装通信测试 - 讲解篇

    文章目录 一. Express框架的安装: 通过cmd命令配置package.json ,cmd命令,依次如下: package.json 文件的代码更新后如下: index.js 代码如下: 简单的 ...

  4. ssm框架整合_框架整合战斗压缩粮篇SpringCloud+SpringBoot+SSM

    各位小伙伴今天又敲了多少Bug了,今天改Bug又花了多长时间啦,我们每天就是敲Bug,敲完改,改完敲,习惯就好啦,心态摆正.Debug起来!!! 上次是Dubbo整合,今天终结篇Cloud整合,不要废 ...

  5. b2c项目基础架构分析(二)前端框架 以及补漏的第一篇名词解释

    b2c项目基础架构分析(二)前端框架 以及补漏的第一篇名词解释 继续上篇,上篇里忘记了也很重要的前端部分,今天的网站基本上是以一个启示页,然后少量的整页切换,大量的浏览器后台调用web服务局部.动态更 ...

  6. SSM框架学习总结第零篇--框架是什么

    SSM框架系列文章: SSM框架学习总结第零篇–框架是什么 SSM框架学习总结第一篇–MyBatis SSM框架学习总结第二篇–Spring SSM框架学习总结第三篇–Spring MVC SSM框架 ...

  7. 万字长文+图文并茂+全面解析微前端框架 qiankun 源码 - qiankun 篇

    写在开头 微前端系列文章: 基于 qiankun 的微前端最佳实践(万字长文) - 从 0 到 1 篇 基于 qiankun 的微前端最佳实践(图文并茂) - 应用间通信篇 基于 qiankun 的微 ...

  8. hutol json null值没了_JSON数据处理框架Jackson精解第一篇-序列化与反序列化核心用法...

    Jackson是Spring Boot默认的JSON数据处理框架,但是其并不依赖于任何的Spring 库.有的小伙伴以为Jackson只能在Spring框架内使用,其实不是的,没有这种限制.它提供了很 ...

  9. java移动端接口测试_走进Java接口测试之测试框架TestNG数据驱动(入门篇)

    前言 我们在前面的文章中,和大家分享过接口自动化测试一些基本的实现方法,但是,你很快就会发现,如果在测试脚本中硬编码测试数据的话,测试脚本灵活性会非常低.而且,对于那些具有重复的请求,而只是测试入参不 ...

最新文章

  1. underscorejs之 _.indexBy(list, iteratee, [context])
  2. 少量数据训练语音识别的思路
  3. vs2012中使用localdb实例还原一个sql server 2008r2版本的数据库
  4. python 命令行参数-Python处理命令行参数
  5. 第一章:数组与指针概念剖析
  6. 3Sum探讨(Java)
  7. 《Effective C#》的读书笔记
  8. 杭州计算机学校哪家好,杭州2021年哪所计算机学校比较好
  9. Hadoop 新增删除节点
  10. 疲劳驾驶监测方案_【Nano Energy】TENG用于驾驶员驾驶状态监测
  11. java中biglong_Java的long和bigint长度对比详解
  12. stm32内部低速rtc_STM32时钟RCC详解
  13. 实用分享-Visual Studio图像查看插件(Image Watch)
  14. sublime text 显示 typescript高亮
  15. tp5 + 百度编辑器 +七牛云存储的实现办法
  16. 买哪个股票稳赚,三类股票,可以买了
  17. ShaderJoy —— “圆点消散” 的实现 【GLSL】
  18. uniapp父子组件传值
  19. `英语` 2022/8/18
  20. 【OpenCV】学习笔记(一):OpenCV4.5.5文件介绍

热门文章

  1. 飞机大战游戏python_基于Python的飞机大战游戏
  2. 微信公众号开发——(first)公众号注册详细步骤
  3. JAVA20w45a,我的世界Java版20w45a
  4. python手机号码加密_Python3加密解密的坑
  5. Java⽇志框架学习笔记
  6. Python_Pandas
  7. Python基础_07_面向对象1
  8. VINTF供应商接口对象
  9. 国宝拜年 新生大熊猫“天团”送出最萌猪年祝福
  10. SGI STL空间配置