Spring Security笔记

创建个项目

 

 引入Spring Web和Spring Security 即可

 

 写个Controller接收请求  转发重定向都可以

 static下定义两个页面

login.html页面  用来登录

main.html如果可以跳到这里,说明登录成功

启动运行程序

我们访问登录接口 或者是访问静态资源都会重定向到这个页面

 这个页面说明 Spring Security已经生效

任何访问资源,都需要此操作登录再操作    

用户名 user

密码是启动时在控制台输出的这串    且每次启动都是不一样的

也就是说引入Spring Security依赖后,对接口访问和静态页面的访问都进行了控制

首先,第一点,即使我不觉得你的登录页面丑,用户名,密码总要去数据库查询出来的,不可能,每次用user,然后去看控制台

那么需要实现两个接口

UserDetailsService 和 PasswordEncode 命名也好记

现在大概了解下UserDetailsService

 

 返回的这个UserDetails

 而返回的UserDetails也是个接口,正常肯定由个实现类

。。。。。

 注意User这个类,可能和我们平时定义的User注意要区分,另外  User里面的password是数据库查出来的,而不是前端传进来的

大概原理是这样,前端传进来一个userName,然后我们去查数据库,没有,那么就没有,有的话,将密码,权限,什么乱七八糟的交给它

我们需要自定用户名密码这些的话,除了要实现UserDetailsService还要实现PasswordEncode

大概了解下PasswordEncode

 其实在我们引入Spring Security时候可以看出来  Spring Security自带默认肯定有这么个实例了

 

 测试一下这个加密

那么Spring Security是如果判断加密后的密码和原来的密码是否相同呢

 且加密后的密码是单向的,不知道的原始密码是无法破解,.......这个无法破解还是算了

那么这里就是大概原理了解了一点点  一丢丢

那么可以这么说:这个PasswordEncode就是对我从数据库通过用户名找到的密码进行加解密的

下面我们来实现自定义的登录逻辑:但是Spring Security有要求,就是你要实现自定义的登录逻辑,需要容器内先要有个PasswordEncode的实例

需要写个配置类

 另外还要写个类实现UserDetailsService接口

现在启动程序   控制台不再打印密码

 输入admin  123456就可以访问了

自定义登录逻辑就写完了

那么如何自定义登录页面呢

实现自定义登录页面很简单

让原先定义的配置类 继承 WebSecurityConfigurerAdpter

 

这样一来,Spring Security就将页面访问控制权交给了我们自己  它的页面就失效

但是随之带来的问题是,我们现在既可以访问login.html   main.html 好像访问控制权限已经完全失效了

那么就需要授权方面的一些什么什么什么的

重新启动程序,发现所有页面又都没不能访问了

上面的写法意思就是所有请求,都必须认证,  也就是说,这样写,把门都堵死了,那么开个门

启动程序

但是又出现个问题,就是登录没有反应 

 发现Spring Security并没有拦截我们的登录请求,就是根本没进这个方法来

还是没反应   关闭csrf防护  不知道

现在登录终于访问方法了

 但是放心debug后  页面报错

原因时,登录成功后没有指定跳转到哪个页面 

控制器根本没进来,也就是一切还是Spring Security控制着

需要告诉Spring Security登录成功后跳转到哪个页面 

启动 

 原因在于Spring Security要求  登录成功后的跳转页面必须是Post请求

 

 也就是说原先的登录就是摆设

,当用户名,密码输入错误的时候,  比如说,当某些时候,业务需要让它去error页面的情况如何操作呢

先自定一个error页面

 

 如果登录失败

关于设置请求账户和密码的参数名

 那么Spring Security具体是怎么做到的

查看UsernamePasswordAuthenticationFilter

 原来你是这么干的

 如何改掉固定参数名

这样的话就改掉了,那么我们自定义的登录页面也需要修改下

下面看一个问题,它其实是转发到我们的控制去

但是直接让它在这里进行外部资源访问,它是做不到的

 当然我们可以转发到控制器再进行重定向

但是直接让它

 重写AuthenticationSuccessHandler

换一种写法,显得很low

注释掉

 

现在很多项目都是前后端分离

 大概理解.......

输入admin  123456

这种时候就比百度难多了

需要干点事

 

 

 注意:password为null??????? 这是Spring Security考虑到安全原因输出为null

上面这些信息不就是这里放进去的吗

 自定义登录成功处理器就这么回事,也是不能和failureForwardUrl共存的

下面自定义登录失败处理器,那不就是照葫芦画瓢么

 

 

 

 运行自己可以试下

授权认证,其实和MVC拦截器比较类似,拦截或者放行

 上面anyRequest就是所有请求都需要做什么事  一般都是.anyRequest().authenticated().即都需要被认证,即登录后可以访问

而anyMatchers就是匹配某些,实际工作中可以这么配置如下

 比如说一般

static下有js,css,images等

 配置下

这样就可以访问到了,即使你没有登录

 关于regexMathcers

很明显,是一个正则的匹配方式

另外无论是antMathcers还是regexMathcers不单只有上面演示的一个参数的方法

还有一个两个参数的方法

 HttpMethod就是Http的请求方式,

这里就用regexMathcers演示,antMathcers也一样的

 

 

 说明不光可以对静态文件放行,还可以对接口放行

另外一个就是如果传入POST,或者GET等等,就要注意,接口上的请求方式了,必须吻合

例如   这种时候要么@GetMapping要么@RequestMapping

如果用@Post或者其他

 这样就会出问题

关于mvcMathcers

它主要配置了一个servletPath的情况

这个servletPath,指的就是

 在没有使用Spring Security之前,这样配置就是说所有的访问

localhost:8080/xxxx这么个意思

但是如果使用了Spring Security,再这样配置是不行的

比如我现在配置了这个

访问  localhost:8080/xxxx/demo  直接跳到了

 原因

也就是说用了Spring Security之后这个配置难道就不能配了?该如何解决

试下

 

现在我们大概了解

关于Spring Security的访问控制方法

我们点击

 可以看到有6个访问控制

 内置访问控制介绍:

1.permitAll:允许任何人都可以来访问

2.denyAll:所有人都不能访问

3.anonymous:匿名访问,和permitAll相似,只不过anonymous会到一个拦截连

4.authenticated:都需要相应认证

5.fullyAuthenticated:完全认证

6.rememberMe:记住我功能

常用的就是permitAll和authenticated,我们已经用过了,还有一个rememberMe

关于权限判断

这里讲的是登录之后

hasAuthority()有某个权限可以访问

hasAnyAuthority()就是用户具备给定权限中的某一个就可以访问

注意权限  比如   "asd"        "aAd"  是严格区分大小写的

 而上面判断的权限就是自定义登录逻辑时候指定的

 演示一下

 

 

admin  123456

 

 

说明都是OK的,那么我们现在将权限改掉

 重启

 

 

403 Forbidden一般就是权限不足的错误

那么如果是这样的话

 就可以了

上面是用户具有某些权限的判断,下面演示关于用户具有某些角色的判断

这个角色的判断,其实和权限的判断一样,在一开始登录时候自定义登录逻辑时候就可以放进去

只是当时没有写,下面就先在自定义登录逻辑里把角色加进去演示

角色的写法  ROLE_是固定写法,告诉SpringSecurity这是角色信息   abc就是角色  当然可以写多个

如果你写ROLE_abc,程序启动就会报错   且严格区分大小写

启动自己测试下

符合其中一个就行

那么下面这种情况呢

上面是权限  和  角色  对登录用户的访问控制

还有

是根据 IP地址  来对访问进行控制

比如说现在有个后端管理,只允许某个IP地址的用户进行操作,或者只允许自己服务器IP登录满足于这样需求的

这里注意下,因为是本机测试,输入localhost和输入127.0.0.1 或者是本机IP地址是不一样的,演示下 

 查看控制台

我们用127.0.0.1试下

 

本机ip地址

 

那么演示IP地址判断的话,就需要用本机IP地址了

这里指定127.0.0.1  能不能用192.168.10.71访问 main1.html呢

 先用127.0.0.1测试

 

 

 127.0.0.1可以访问

那么用另外个IP

 

 

权限判断    角色判断   IP地址判断  如果没有指定权限或者指定角色或者指定IP

那么都会跳转到403页面,但是浏览器的哪个页面也太丑了,体验好点就需要自定义了

下面是自定义403处理方案

实现AccessDeniedHandler

 自己想像

 

 演示,因为现在只允许127.0.0.1去main1.html

 

 

下面介绍access方法使用

我们可以点进去看它里面  权限   角色  IP 全都是用的access方法

 

 

 和原先效果是一样的

 这个叫access表达式

access就是权限  角色   IP 判断的底层实现

在项目中很有可能出现需要自定义方法实现权限控制的情况

比如说,我们的项目现在需求是这样的,有没有访问当前URL的权限,有就可以访问,没有就不让访问

那么我们就来自定义access

自定义  方法名随意 

 

 

测试

 

原因是我们没把这个权限在自定义登录逻辑里加进去

重启  测试

 

可以到main1原因

@某个bean名是固定写法

 以上都是通过配置类去实现访问控制

其实Spring Security提供了通过注解的方式控制访问

通过在启动类或者配置类添加@EnableGlobalMethodSecurity 开启Spring Security注解方式控制

如果设置的条件允许,程序正常执行,如果权限不允许报500,就是说先会请求到登录页,登录后如果没有权限报500

org.springframework.security.access.AccessDeniedException:不允许访问

这些注解可以写到Service接口或方法上,也可以写道Controller或者Controller的方法上,通常情况下都是卸载控制器方法上的,控制接口URL是否允许被访问

@Secured是专门用来判断是否具有角色的.能写在方法或类上.参数要以ROLE_开头

演示 先修改下配置类  就是所有都需要验证,只留登录页  error页面

 启动类上加上该注解

 

自定义登录逻辑里是有这个角色的,大小写严格区分   ROLE_

 那么这样就是可以访问的

测试

 

修改下

这个@Secured("ROLE_abc")也可以不用里面非加括号  且严格区分大小写,必须写ROLE_ 

 

 看控制台

注意

下面是后来复习时重敲了一遍    一直报自定义的那个异常

 下图是后来复习时候在application.properties里加了

 

 再介绍两个注解   @PreAuthorze   和  @PostAuthorize

@PreAuthorze:表示访问方法或类在执行之前先判断权限,大多情况下都是使用这个注解,注解的参数和access()方法参数取值相同,都是权限表达式access("hasAuthority('ROLE_abc')")

@PostAuthorize:表示方法或类执行结束后判断权限,此注解很少被使用到

现在演示使用

首先

还可以写@PreAuthorize("hasRole('ROLE_abc')")

还可以写@PreAuthorize("hasAnyAuthority('admin')")

关于RememberMe功能

Spring Security中Remember Me为"记住我"功能,用户只需要在登录时添加 remember-me复选框,取值为true,Spring Security会自动把用户信息存储到数据源,以后就可以不登陆进行访问.

Spring Security实现Remeber Me功能时,底层实现以来Spring-JDBC,所以需要导入Spring-JDBC.

但现在大部分使用的是Mybatis框架,很少直接使用Spring-JDBC,所以可以直接导入mybatis启动器加Mysql驱动

<dependency>
<groupId> org.mybatis.spring.boot </groupId>
<artifactId> mybatis-spring-boot-starter </artifactId>
<version> 2.1.1 </version>
</dependency>
<!-- mysql 数据库依赖 -->
<dependency>
<groupId> mysql </groupId>
<artifactId> mysql-connector-java </artifactId>
<version> 8.0.18 </version>
</dependency>

导入之后在 application.properties里配置好数据源,根据自己实际情况配置

spring.datasource.driver-class-name = com.mysql.cj.jdbc.Driver
spring.datasource.url = jdbc : mysql : //localhost : 3306/security?
useUnicode = true&characterEncoding = UTF-8&serverTimezone = Asia/Shanghai
spring.datasource.username = root
spring.datasource.password = root

那么数据库连接就没有问题了

下面配置Remeber Me功能

登录页面

测试  启动后看下数据库

 自动建了张表

username用户名

series主键

token令牌

last_used最后登录时间

现在去登录

 

登录成功的话,第一次该表会自动创建  series是主键   记得第二次启动把建表注释掉  不然会报错表已经存在

 

这个记住我功能,没仔细研究,Cookie会有一个remember-me,定时清楚,关闭浏览器后定时消失

将网页关掉,再次访问localhost:8080/main.html 就不需要再次登录

这里默认记住我功能的时间是2周,可以配置时间

测试OK

注意

Thymeleaf中Spring Security的使用

Spring Security可以在一些视图技术中进行控制显示效果.例如JSP或Thymeleaf.在非前后端分离且使用SpringBoot的项目中使用Thymeleaf做为视图展现技术。

Thmeleaf对Spring Security的支持都放在thymeleaf-extras-springsecurity中

所以需要在项目中添加依赖,和Thmeleaf依赖

<!--thymeleaf springsecurity5 依赖 -->
<dependency>
<groupId> org.thymeleaf.extras </groupId>
<artifactId> thymeleaf-extras-springsecurity5 </artifactId>
</dependency>
<!--thymeleaf 依赖 -->
<dependency>
<groupId> org.springframework.boot </groupId>
<artifactId> spring-boot-starter-thymeleaf </artifactId>
</dependency>

 在html页面中引入Thmeleaf和security的命名空间

<html xmlns = "http://www.w3.org/1999/xhtml"
xmlns:th = "http://www.thymeleaf.org"//Thmeleaf命名空间
xmlns:sec = "http://www.thymeleaf.org/thymeleaf-extras-//security命名空间
springsecurity5" >

可以在 html 页面中通过 sec:authentication="" 获取
UsernamePasswordAuthenticationToken 中所有 getXXX 的内容,包含父类中的 getXXX
内容。
根据源码得出下面属性:
name :登录账号名称
principal :登录主体,在自定义登录逻辑中是 UserDetails
credentials :凭证
authorities :权限和角色
details :实际上是 WebAuthenticationDetails 的实例。可以获取 remoteAddress (
户端 ip) sessionId ( 当前 sessionId)
演示下
templates新建个demo.html

在Controller里做个页面跳转  加个内部转发

 

 

测试

 

 登录后访问demo接口   由于是复习时写的 这里

 

 

 上面就是在Thmeleaf中获取登录用户属性相关操作

demo.html

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:th="http://www.thymeleaf.org"
xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity5">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
登录账号:<span sec:authentication="name"></span><br/>
登录用户名:<span sec:authentication="principal.username"></span><br/>
凭证:<span sec:authentication="credentials"></span><br/>
权限和角色:<span sec:authentication="authorities"></span><br/>
客户端地址:<span sec:authentication="details.remoteAddress"></span><br/>
sessionId:<span sec:authentication="details.sessionId"></span><br/>
</body>
</html>

下面说下Thmeleaf中进行权限判断

比如有增删改查的按钮,哪些用户根据权限判断,显示各自权限可以看到的按钮

也可以根据角色判断

哪些按钮可以点,哪些按钮不能点,哪些按钮对谁显示,不对谁显示

比如在自定义逻辑类里

demo.html

 测试

 

 

退出功能很简单,演示   价格/logout的超链接即可

 测试

 

 点击退出

如果说加了上下文,也只要写/logout

地址栏会有个?logout  其实这就已经退出了,再访问其他页面都会跳转到登录页面

如果不想要后面跟着的?logout,也可以配置

可以自己测试

 如果html那边不想写/logout

 测试

 

 点击退出  一样可以到登录页  其实也没必要的

下面了解下CSRF

从刚开始学习 Spring Security 时,在配置类中一直存在这样一行代码:
http.csrf().disable() ; 如果没有这行代码导致用户无法被认证。这行代码的含义是:关闭
csrf 防护。
什么是 CSRF
CSRF Cross-site request forgery )跨站请求伪造,也被称为 “OneClick Attack” 或者
Session Riding 。通过伪造用户请求访问受信任站点的非法请求访问。
跨域:只要网络协议, ip 地址,端口中任何一个不相同就是跨域请求。
客户端与服务进行交互时,由于 http 协议本身是无状态协议,所以引入了 cookie 进行记录客
户端身份。在 cookie 中会存放 session id 用来识别客户端身份的。在跨域的情况下, session id
可能被第三方恶意劫持,通过这个 session id 向服务端发起请求时,服务端会认为这个请求是
合法的,可能发生很多意想不到的事情。
Spring Security 中的 CSRF
Spring Security4 开始 CSRF 防护默认开启。默认会拦截请求。进行 CSRF 处理。 CSRF 为了保
证不是其他第三方网站访问,要求访问时携带参数名为 _csrf 值为 token(token 在服务端产生 )
的内容,如果 token 和服务端的 token 匹配成功,则正常访问。

讲人话:就是跨域情况下,sessionId有可能被第三方劫持,比如你管理员登录账号,跨域情况下如果被第三方劫持,知道了你的sessionId,第三方很可能冒充管理员. 

Spring Security4开始,不管你是不是跨域请求,都会做CSRF防护.默认开启

要求访问着携带参数名为_csrf值为token,和服务端进行匹配.至于第三方如何劫持.不懂

 

 

 启动测试

如果你不携带

是登录不了的,这里只做大概了解

学习时候csrf关闭,但是正式环境还是要打开的

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

hrui0706

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值