一:搞清楚认证与权限

1.1:什么是认证?

认证就是身份的核实,在我们生活中无处不在。譬如说你坐高铁需要拿着你的身份证以及你的英俊漂亮的脸,过闸机时那个操作相对于铁路局的操作系统而言就是需要对你进行认证,检查你是否有买当天的票,检查你与身份证以及票是否是同一个人。当我们使用别人的身份证进去时就亮红灯,不给进。这就是认证。

1.2:什么是权限?

接着上面的认证,咱们进去候车厅之后,然后等车,上车,接着找自己的位置。那么你是坐一等坐呢?还是二等座?亦或是三等座(站票)?这就取决于你买票的时候所选的坐席以及付出的money了(三等座于二等座同价不必抬杠)。你能坐到什么的位置就是你的权限。

1.3:小结

认证就是对身份的校验,权限就是你这个身份所拥有那些操作。

1.4:RBAC(基于角色的访问控制)

其基本思想是,对系统操作的各种权限不是直接授予具体的用户,而是在用户集合与权限集合之间建立一个角色集合。每一种角色对应一组相应的权限。一旦用户被分配了适当的角色后,该用户就拥有此角色的所有操作权限。这样做的好处是,不必在每次创建用户时都进行分配权限的操作,只要分配用户相应的角色即可,而且角色的权限变更比用户的权限变更要少得多,这样将简化用户的权限管理,减少系统的开销。

二:Spring-Security(安全认证框架)

1.1:什么是Spring-Security?

Spring Security是 Spring提供的安全认证服务的框架。 使用Spring Security可以帮助我们来简化认证和授权的过程。官网:Spring-Security

  1. SpringSecurity是Spring家族的一个安全框架, 简化我们开发里面的认证和授权过程, (登陆, 访问url时的权限控制 secuirty帮我们做了)
  2. SpringSecurity内部封装了Filter(只需要在web.xml容器中配置一个过滤器–代理过滤器,真实的过滤器(12个)在spring的容器中配置)
  3. 常见的安全框架
    1: Spring的 SpringSecurity 配置复杂 有个好老爸(spring) 无缝整合 链式模式
    2: Apache的Shiro http://shiro.apache.org/ 比较简单 apache 写整合 外观者模式

1.2:小结

为什么要用spring-security?那么麻烦的配置咱们还用它作甚?不用不行啊,因为企业中谁不用spring的东西啊?sping已经成为了企业的春天了。正因如此,为了更好的使用安全框架就用spring-security了。

三:Spring-Security入门

3.1:目标

使用Spring Security进行控制: 网站(一些页面)需要登录才能访问(认证)

3.2:环境

3.2.1:idea、tomcat、maven

1:在idea中创建maven工程的web项目,pom.xml文件引入spring以及spring-secruity依赖,我这里引入了spring的多个依赖,后面用到就不用再引入了。

     <spring.security.version>5.0.5.RELEASE</spring.security.version><!-- Spring --><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>${spring.version}</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-beans</artifactId><version>${spring.version}</version></dependency><!--springmvc--><dependency><groupId>org.springframework</groupId><artifactId>spring-web</artifactId><version>${spring.version}</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-webmvc</artifactId><version>${spring.version}</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-jdbc</artifactId><version>${spring.version}</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-aspects</artifactId><version>${spring.version}</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-context-support</artifactId><version>${spring.version}</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-test</artifactId><version>${spring.version}</version></dependency><dependency><groupId>org.springframework.security</groupId><artifactId>spring-security-web</artifactId><version>${spring.security.version}</version></dependency><dependency><groupId>org.springframework.security</groupId><artifactId>spring-security-config</artifactId><version>${spring.security.version}</version></dependency><dependency><groupId>org.springframework.security</groupId><artifactId>spring-security-taglibs</artifactId><version>${spring.security.version}</version></dependency>

2:配置web.xml配置文件(这里主要配置一个代理过滤器(spring-security)以及一个核心控制器(springMVC)

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://java.sun.com/xml/ns/javaeehttp://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"version="3.0"><filter>
<!--  filter-name:固定为springSecurityFilterChain,不能修改。容器启动时,
会从spring容器中获取这个filtername的bean对象(security启动时创建的bean name)
可以修改:必须在spring容器中配置一个bean对象为你修改后的名称--><filter-name>springSecurityFilterChain</filter-name>
<!--   代理过滤:自己不干活,拦截的请求转给security的过滤器(springSecurityFilterChain)去处理--><filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class></filter><filter-mapping><filter-name>springSecurityFilterChain</filter-name><url-pattern>/*</url-pattern></filter-mapping><!-- 使用DispatcherServlet或者使用contextLoaderListener 都一样,只要启动容器即可   --><servlet><servlet-name>dispatchServlet</servlet-name><servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class><init-param><param-name>contextConfigLocation</param-name><param-value>classpath:spring-security.xml</param-value></init-param><load-on-startup>1</load-on-startup></servlet><servlet-mapping><servlet-name>dispatchServlet</servlet-name><url-pattern>*.do</url-pattern></servlet-mapping>
</web-app>

3:配置spring-security.xml(这里就是配置用户的认证权限)

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:security="http://www.springframework.org/schema/security"xmlns:http="http://www.springframework.org/schema/security"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"><!--第一步:拦截规则auto-config: 自动装配,处理login页面,认证的处理....use-expressions: 是否使用spel表达式 与下面的intercept-url 的access属性 有关true: access的值可以为hasAnyRole hasAnyAuthority...false: access的值必须使用ROLE_打头的 角色 ROLE_大写intercept-url: 拦截url配置pattern: 拦截的匹配规则 /** 所有的access: 要访问必须具备有这个权限, 给拦截的url标定权限这里的意思:要访问/**,登陆用户必须拥有ROLE_ADMIN的角色--><security:http auto-config="true" use-expressions="false"><security:intercept-url pattern="/**" access="ROLE_ADMIN"/></security:http><!--第二步:认证管理器(authentication-manager)配置认证信息的提供者(authentication-provider)提供登录用户信息(user-service)在内存中写死一个用户信息(user 包含3个字段数据)name:用户名authorities:该用户拥有的那些权限?password:用户登录的密码(默认是加密的,先用{noop}标注不适用加密就是使用明文)--><security:authentication-manager><security:authentication-provider><security:user-service><security:user name="admin" authorities="ROLE_ADMIN" password="{noop}admin"/></security:user-service></security:authentication-provider></security:authentication-manager>
</beans>

4:在项目的web-app/目录下创建一个index.html页面,我们以往不加spring-security,启动项目就会直接访问咱们的index.html页面。现在咱们加上后看看能否直接访问index.html页面?

5:启动项目

这时会跳出一个奇怪的页面,咱们可没有实现这个页面。莫慌,看到这个页面就对了。这就说明咱们加入的spring-security校验生效了。这个就是security的用户验证界面。当然了,相信没有那个项目愿意使用security的原生认证页面。这个当然可以自定义。后面再说。我们随便输入一个用户密码进去看看行不行?

发现随便输入的用户或者密码给我报错了,这个也是spring-security给咱们的校验失败页面。

6:接着咱们使用在spring-security.xml配置文件里面写死在内存中的用户admin admin登录上去后看看咋样?出现如下的页面:

这又是啥?别急,这个是登录成功后默认跳转的访问资源,由于我们的项目里面没有这个资源所以报错404咱们不管他,直接访问我们自定义的index.html看看能不能访问。如下如:

看,可以访问了,也就是说,通过了spring-security的认证后就可以访问咱们的资源了。哈。到这里咱们已经对spring-security.xml做了入门了。是不是也没有那么难?

3:入门总结

使用spring-security的步骤

  1. 创建一个maven的web项目
  2. 引入spring相关依赖
  3. 配置web.xml(前端控制器,springSecurity权限相关的过滤器 DelegatingFilterProxy, 过滤器的名称不能修改,一定是springSecurityFilterChain)
  4. 创建spring-security.xml(security:http 自动配置,使用表达式的方式完成授权,只要具有ROLE_ADMIN的角色权限才能访问系统中的所有功能; 授权管理器,指定用户名admin,密码{noop}admin,具有ROLE_ADMIN的角色权限)

Spring-Security进阶

1:承上启下

前面我们已经完成了Spring Security的入门案例,通过入门案例我们可以看到,Spring Security将我们项目中的所有资源都保护了起来,要访问这些资源必须要完成认证而且需要具有ROLE_ADMIN角色。但是入门案例中的使用方法离我们真实生产环境还差很远,还存在如下一些问题:
5. 项目中我们将所有的资源(所有请求URL pattern=/**)都保护起来,实际环境下往往有一些资源不需要认证也可以访问,也就是可以匿名访问(静态资源)。
6. 登录页面是由框架生成的,而我们的项目往往会使用自己的登录页面。
7. 直接将用户名和密码配置在了配置文件中,而真实生产环境下的用户名和密码往往保存在数据库中。
8. 在配置文件中配置的密码使用明文,这非常不安全,而真实生产环境下密码需要进行加密。
接下来我们改进以上问题

2:定下目标

  1. 配置可匿名访问的资源(不需要登录,权限 角色 就可以访问的资源)
  2. 使用指定的登录页面(login.html)
  3. 从数据库查询用户信息
  4. 对密码进行加密
  5. 配置多种校验规则(对访问的页面做权限控制)
  6. 注解方式权限控制(对访问的Controller类做权限控制)
  7. 退出登录

3: 配置可匿名访问的资源(不需要登录,权限 角色 就可以访问的资源)

3.1:在项目中创建js、css目录并在两个目录下提供任意一些测试文件

3.2:在浏览器中直接输入访问网址http://localhost:8580/css/login.css

发现它又跳到spring-security的登录页面去了。

3.3:在spring-security.xml文件中配置,指定哪些资源可以匿名访问

然后我们在网址上面直接输入:http://localhost:8580/js/vue.js看看能否直接访问资源?如下图:

不难发现,我们的配置生效了。直接越过了spring-security的校验访问指定的静态资源。

4:使用指定的登录页面(login.html)

4.1:提供login.html作为项目的登录页面(自己随便写一个登录界面)

详细页面源码如下:

4.2: 修改spring-security.xml文件,指定login.html页面可以匿名访问

咱们这里已经添加了fail.html页面了,这个失败页面自行添加。随便一个页面都可以。

咱们访问一下http://localhost:8580/项目看看?

由上图可以看出,自定义登录页面也已经生效了。接下来我们随便输入一个错误的看看会不会跳到咱们自定义的错误的页面?

接下来咱们使用admin admin 正确的用户密码登录看看?

5:从数据库查询用户信息

5.1:分析

上面咱们是在配置文件中写死了一个用户在内存中,这样写耦合太高了,一般我们的用户都是配置到数据库中的。那么怎么才能从数据库中获取用户?又怎么让spring-security认咱们定义的用户?首先我们定义一个UserService类,然后从表中查询用户信息(用户名+密码等)封装到UserService中这并不难完成。但是怎样才能让spring-security认咱们自定义的这个用户呢?这时spring-security已经为咱们想好了,想要解耦,必须依赖接口。spring-security就提供一个接口【UserDetailsService】,咱们实现的UserService类必须实现它的接口,并把自定义的类放入spring容器中,在spring-security.xml配置文件中配置上去,告诉spring-security用这个用户校验即可。分析以及好了,那么接下来咱们就实现它。

5.2:定义一个UserService类实现UserDetailsService重写其方法

public class UserService implements UserDetailsService {/*** 这个方法是security登录时调用* @param username* @return* @throws UsernameNotFoundException*/@Overridepublic UserDetails loadUserByUsername(String username) throws UsernameNotFoundException{//通过用户名获取用户信息User user = getUserByDb(username);//为org.springframework.security.core.userdetails.User准备参数//参数1:用户名//参数2:用户密码//参数3:权限集合//创建权限集合List<GrantedAuthority> authorityList = new ArrayList<>();//创建权限SimpleGrantedAuthority sga = new SimpleGrantedAuthority("ROLE_ADMIN");//往权限集合里面放权限authorityList.add(sga);//new 这个方法的返回值org.springframework.security.core.userdetails.User userDetail =new org.springframework.security.core.userdetails.User(username,                       "{noop}" + user.getPassword(),authorityList);//返回spring-secur需要的用户信息return userDetail;
}/*** 模拟从数据库中根据用户名查询用户信息(这里主要是拿密码)* @param username* @return*/private User getUserByDb(String username){User user = new User();user.setPassword("888888");return null;}

5.3: 修改配置文件,将原先写死的用户信息注释,然后通过spring的方式配置进去。如下图:

5.4:重新部署服务,然后直接访问index.html会出现登录界面,接着输入错误的用户名或者密码,都会跳转到错误页面。上面咱们设置的密码是888888,用户名随意。


咱们输入正确的密码看看?

6:对密码进行加密

上面咱们使用的都是密码明文,实际工作这时不允许的。接下来使用加密的密码来认证。数据库中存储的密码应该使用不可逆加密算法进行加密。即便数据库被泄露了,也不至于使用户的账户安全造成损失。
常见的密码加密方式有:

  • 对称加密:3DES、AES、DES:使用对称加密算法,可以通过解密来还原出原始密码 可逆加密
  • 非对称加密: MD5、SHA1、Bcrypt:使用单向HASH算法,无法通过计算还原出原始密码,但是可以建立彩虹表进行查表破解, MD5可进行加盐加密,保证安全。

6.1:分析

首先咱们分析一下,数据库的密码使用什么样的加密方式?配置文件需要怎么配置?好了,spring-security已经提供了多种加密器给我们去匹配加密后的密文。我们这里使用Bcrypt加密算法!
bcrypt:将salt随机并混入最终加密后的密码,验证时也无需单独提供之前的salt,从而无需单独处理salt问题。spring security中的BCryptPasswordEncoder方法采用SHA-256 +随机盐+密钥对密码进行加密。SHA系列是Hash算法,不是加密算法,使用加密算法意味着可以解密(这个与编码/解码一样),但是采用Hash处理,其过程是不可逆的。

  • 加密(encode):注册用户时,使用SHA-256+随机盐+密钥把用户输入的密码进行hash处理,得到密码的hash值,然后将其存入数据库中。
  • 密码匹配(matches):用户登录时,密码匹配阶段并没有进行密码解密(因为密码经过Hash处理,是不可逆的),而是使用相同的算法把用户输入的密码进行hash处理,得到密码的hash值,然后将其与从数据库中查询到的密码hash值进行比较。如果两者相同,说明用户输入的密码正确。
  • 这正是为什么处理密码时要用hash算法,而不用加密算法。因为这样处理即使数据库泄漏,黑客也很难破解密码。

6.2: 使用Bcrypt加密很简单,如下如:

#### 6.3:现在咱们使用这个密文代替咱们之前写死的888888密码。修改UserService类如下图:

6.4:修改spring-security.xml配置文件如下图:

6.5:测试效果

6.6:配置多种校验规则(对访问的页面做权限控制)

首先定义几个简单的页面在webapp下a.html、b.html、c.html、d.html然后修改spring-security.xml配置文件。测试配置多种校验规则。配置文件修改如下:

6.7:验证这几种校验规则与权限如下图:

7:注解方式权限控制(对访问的Controller类做权限控制)

7.1:分析(怎样使用注解方式做权限控制?)

spring家族都可以支持注解开发,一样的,这里也可以使用注解开发,spring-security使用注解开发的步骤也是有2步

  • 1:配置文件开启注解支持,扫描controller包。
  • 2:controller类的方法上使用注解配置权限控制

7.2:添加一个controller包以及类到web项目中,提供测试。如下图:

7.3:spring-secur.xml配置文件的修改

7.4:测试注解权限校验

8:退出登录

这个就比较简单了

8.1:spring-securt.xml配置退出登录如下图:

8.2:测试退出登录如下图:

三:总结

什么是RBAC?
spring-security是什么?
如何使用简单的spring-security做认证控制权限?
如何在controller上面使用spring-security注解的方式做权限校验?

END…

0到1使用spring-security(Spring的安全认证框架)相关推荐

  1. Spring security (一)架构框架-Component、Service、Filter分析

      想要深入spring security的authentication (身份验证)和access-control(访问权限控制)工作流程,必须清楚spring security的主要技术点包括关键 ...

  2. Spring Security使用数据库登录认证授权

    一.搭建项目环境 1.创建 RBAC五张表 RBAC,即基于角色的权限访问控制(Role-Based Access Control),就是用户通过角色与权限进行关联. 在这种模型中,用户与角色之间,角 ...

  3. Spring Security | 轻松搞定认证授权~

    文章目录 一.Spring Security 简介 二.整合 Spring Security 1.创建项目,导入依赖 2.创建数据库,搭建环境 3.配置数据库 4.创建实体类 5.实现 UserMap ...

  4. Spring Security关于用户身份认证与授权

    Spring Security是用于解决认证与授权的框架. 创建spring项目,添加依赖 <!-- Spring Boot Security:处理认证与授权 --><depende ...

  5. Spring Security + Spring Session Redis——【SecurityContext】和【AuthenticationToken】JSON反序列化问题解决方案

    前置 Spring Session + Redis--自定义JSON序列化解决方案 问题描述 Spring Security + Spring Session使用中Redis,默认序列化方式是JdkS ...

  6. Spring Security 集成 Authing CAS 认证(一)

    01 集成介绍 单点登录 (Single Sign On),英文名称缩写 SSO,意思是在多系统的环境中,登录单方系统,就可以无须再次登录,访问相关受信任的系统.也就是说,只要登录一次单体系统即可. ...

  7. Spring Security+Spring Data Jpa 强强联手,安全管理只有更简单!

    Spring Security+Spring Data Jpa 强强联手,安全管理没有简单,只有更简单! 这周忙着更新 OAuth2,Spring Security 也抽空来一篇. Spring Se ...

  8. Spring Security(一)- SpringSecurity 框架简介

    文章目录 一.SpringSecurity 框架简介 1. 概要 2. Spring Security 与 Shiro 对比 2.1 Spring Security 2.2 SpringSecurit ...

  9. 详解Spring Security的formLogin登录认证模式

    详解Spring Security的formLogin登录认证模式 一.formLogin的应用场景 在本专栏之前的文章中,已经给大家介绍过Spring Security的HttpBasic模式,该模 ...

  10. Spring Security 学习之LDAP认证

    一.前言 LDAP:轻型目录访问协议,即Lightweight Directory Access Protocol (LDAP)是一个访问在线目录服务的协议,最典型例子的就是黄页.电话簿等,主要用于读 ...

最新文章

  1. MySQL 仅保留7天、一个月数据
  2. iOS-获取子视图父控制器
  3. 修改oralce字符集
  4. 数据结构第八篇——链栈
  5. php模板技术smarty,PHP模板技术Smarty
  6. JDBC第二篇 【PreparedStatment、批处理、处理二进制、自动主键、调用存储过程、函数】...
  7. scipy.sparse、pandas.sparse、sklearn稀疏矩阵的使用
  8. php之mvc设计模式的原理和实现
  9. JS中一些常用的函数(持续更新)
  10. rdkit 修改分子
  11. 电压跟随器的特点、作用和应用举例
  12. html对话框取消确定,alert 确定 取消
  13. 华为交换机eth口作用_华为交换机 eth-trunk
  14. Nutch抓取过程简析
  15. HTML和CSS的知识点
  16. 【ERROR】ValueError: Of the four parameters: start, end, periods, and freq, exactly three must be spec
  17. 计算机四级网络工程师
  18. c语言象棋教程下载,C语言程序源代码中国象棋.doc-资源下载在线文库www.lddoc.cn...
  19. HAUT 1262 魔法宝石 暴力思想,多种解决方案
  20. 【击穿、穿透、雪崩】

热门文章

  1. java字符串练习题_java练习题——字符串
  2. win7计算机扫描仪,win7系统怎么用打印机扫描仪功能|win7系统扫描仪功能的使用方法...
  3. 微信模拟地理位置_伪装微信地理位置
  4. Arora is a lightweight cross-platform web browser.
  5. WhatsApp选择了便利而不是隐私,这是解决问题的方法
  6. 冒泡排序Java代码实现
  7. 【依赖高精度点云地图和三维激光雷达的定位方案】正态分布变换(NDT)定位及建图
  8. 微博指数导出csv文件下载说明
  9. oracle中锁表是什么,oracle锁表查询和解锁方法是什么,oracle锁表和解锁
  10. 华为模拟器ENSP下载与安装详细教程(win10 LTSC系统中安装)