Spring Security-02-Spring Security认证方式-HTTP基本认证、Form表单认证、HTTP摘要认证、前后端分离安全处理方案

Lison <dreamlison@163.com>, v1.0.0, 2024.06.01

Spring Security-02-Spring Security认证方式-HTTP基本认证、Form表单认证、HTTP摘要认证、前后端分离安全处理方案

文章目录

  • Spring Security-02-Spring Security认证方式-HTTP基本认证、Form表单认证、HTTP摘要认证、前后端分离安全处理方案
    • 认证方式
    • HTTP基本认证
      • 基本认证简介
      • 基本认证核心API
      • 基本认证的步骤
      • 基本认证的弊端
      • HTTP基本认证代码实现
        • 创建SecurityConfig配置类
        • 测试验证
      • Basic认证详解
        • 基本认证过程
        • 注销Basic认证
    • Form表单认证
      • 表单认证简介
      • 表单认证效果
      • 表单认证中的预置url和页面
      • 自定义表单认证配置
        • 创建SecurityConfig配置类
        • 测试应用
      • 自定义表单认证的登录界面
        • 服务端代码定义
        • 页面定义
        • 测试应用
      • 细化表单认证配置
        • 定义SecurityConfig类
        • 自定义登录页面
        • 定义错误处理页面
        • 测试验证
    • HTTP摘要认证
      • HTTP摘要认证简介
      • HTTP摘要认证核心参数
      • 摘要认证代码实现
        • 编写测试接口
        • 创建SecurityConfig配置类
        • 测试接口
        • HTTP摘要认证弊端
    • 前后端分离时的安全处理方案
      • 前后端分离简介
      • 认证处理时的相关API
        • 页面跳转的相关API
        • 返回JSON格式的处理器
      • 认证成功时的处理方案
        • 1. successHandler()方法
        • 2. onAuthenticationSuccess参数
        • 定义SecurityAuthenticationSuccessHandler类
        • 配置successHandler
        • 验证结果
      • 认证失败时的处理方案
        • failureHandler()
        • 代码实现
        • 配置failureHandler
        • 验证结果
      • 退出登录时的处理方案
        • 1. logoutSuccessHandler()
        • 2. 定义SecurityLogoutSuccessHandler类
        • 配置logoutSuccessHandler
        • 验证结果
      • 未认证时的处理方案
        • 1. authenticationEntryPoint()
        • 2. 定义SecurityAuthenticationEntryPoint类
        • 配置authenticationEntryPoint
        • 验证结果

认证方式

认证: 所谓的认证,就是用来判断系统中是否存在某用户,并判断该用户的身份是否合法的过程,解决的其实是用户登录的问题。认证的存在,是为了保护系统中的隐私数据与资源,只有合法的用户才可以访问系统中的资源。

在Spring Security中,常见的认证方式可以分为HTTP层面和表单层面,常见的认证方式如下:

  • HTTP基本认证;
  • Form表单认证;
  • HTTP摘要认证;

HTTP基本认证

基本认证简介

在Spring Security 4.x版本中,默认采用的登录方式是Http基本认证,该方式会弹出一个对话框,要求用户输入用户名和密码。在每次进行基本认证请求时,都会在Authorization请求头中利用Base64对 “用户:密码” 字符串进行编码。这种方式并不安全,并不适合在Web项目中使用,但它是一些现代主流认证的基础,而且在Spring Security的OAuth中,内部认证的默认方式就是用的Http基本认证。

基本认证核心API

在这里插入图片描述

执行流程如下:

Filter->构造Token->AuthenticationManager->转给Provider处理->认证处理成功后续操作或者不通过抛异常

基本认证的步骤

HTTP基本认证是在RFC2616标准中定义的一种认证模式,它以一种很简单的方式与用户进行交互。HTTP基本认证可以分为如下4个步骤:

  • ①. 客户端首先发起一个未携带认证信息的请求;
  • ②. 然后服务器端返回一个401 Unauthorized的响应信息,并在WWW-Authentication头部中说明认证形式:当进行HTTP基本认证时,WWW-Authentication会被设置为Basic realm=“被保护的页面”;
  • ③. 接下来客户端会收到这个401 Unauthorized响应信息,并弹出一个对话框,询问用户名和密码。当用户输入后,客户端会将用户名和密码使用冒号进行拼接并用Base64编码,然后将其放入到请求的Authorization头部并发送给服务器;
  • ④. 最后服务器端对客户端发来的信息进行解码得到用户名和密码,并对该信息进行校验判断是否正确,最终给客户端返回响应内容。

基本认证的弊端

HTTP基本认证是一种无状态的认证方式,与表单认证相比,HTTP基本认证是一种基于HTTP层面的认证方式,无法携带Session信息,也就无法实现Remember-Me功能。另外,用户名和密码在传递时仅做了一次简单的Base64编码,几乎等同于以明文传输,极易被进行密码窃听和重放攻击。所以在实际开发中,很少会使用这种认证方式来进行安全校验。

HTTP基本认证代码实现

创建SecurityConfig配置类

这里我们先创建一个config配置类,命名为SecurityConfig,并且继承自WebSecurityConfigurerAdapter父类,代码如下:

package com.lison.springsecurity.config.security;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;/*** @className: com.lison.springsecurity.config.security-> SecurityConfig* @description:* @author: Lison* @createDate: 2024-06-01*/
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {@Overrideprotected void configure(HttpSecurity http) throws Exception {//1.配置基本认证方式http.authorizeRequests()//对任意请求都进行认证.anyRequest().authenticated().and()//开启basic认证.httpBasic();}
}

httpBasic()方法,就是用来开启基本认证的,而且默认采用的就是基本认证!

测试验证

访问自己的/hello接口,这时候我们就可以看到浏览器中弹出了一个登陆窗口。提示我们输入自己的用户名和密码 lison/123456,认证成功后,即可访问自己的web接口。

Basic认证详解

基本认证过程

此时的响应码为401,什么情况下会导致401状态码?

在这里插入图片描述

根据401和以上响应头信息,浏览器会弹出一个对话框,要求输入 用户名/密码,Basic认证会将其拼接成 “用户名:密码” 格式,中间是一个冒号,并利用Base64编码成加密字符串xxx;然后在请求头中附加 Authorization: Basic xxx 信息,发送给后台认证;后台需要利用Base64来进行解码xxx,得到用户名和密码,再校验 用户名:密码 信息。

  • 如果认证错误,浏览器会保持弹框;
  • 如果认证成功,浏览器会缓存有效的Base64编码,在之后的请求中,浏览器都会在请求头中添加该有效编码。
注销Basic认证

在成功认证之后,Basic认证会把Authorization认证信息缓存在浏览器中一段时间,之后每次请求接口时都会自动带上,所以直到 用户关闭浏览器才会销毁认证信息,也就是说我们无法在服务端进行有效的注销。

不过在请求注销时,前端也可以手动 在请求头配置一个错误的Authorization,或者在浏览器的命令行执行 document.execuCommand(“ClearAuthenticationCache”)方法 来清空认证信息,但该方式对Chrome浏览器无效。我们在调试基本认证时,可以直接开启无痕模式,避免很多因为缓存造成的问题。

Form表单认证

表单认证简介

对于表单认证,其实在SpringBoot开发环境中,只要我们添加了Spring Security的依赖包,就会自动实现表单认证。在WebSecurityConfigurerAdapter类的config(HttpSecurity http)方法中,可以看到如下默认实现。

在这里插入图片描述

在SpringBoot环境中,默认支持的就是表单认证方式。

表单认证效果

第一个Spring Security项目中实现的效果,其实就是表单认证。每次我们在访问某个Web接口之前,都会重定向到一个Security自带的login登录页面上,这个登录页面,就是表单认证的效果

在这里插入图片描述

表单认证中的预置url和页面

这时候有的小伙伴可能就会很好奇,为什么表单认证会有以上效果?这是因为在默认的formLogin配置中,自动配置了一些url和页面:

  • /login(get): get请求时会跳转到这个页面,只要我们访问任意一个需要认证的请求时,都会跳转到这个登录界面。
  • /login(post): post请求时会触发这个接口,在登录页面点击登录时,默认的登录页面表单中的action就是关联这个login接口。
  • /login?error: 当用户名或密码错误时,会跳转到该页面。
  • /: 登录成功后,默认跳转到该页面,如果配置了index.html页面,则 ”/“ 会重定向到index.html页面,当然这个页面要由我们自己实现。
  • /logout: 注销页面。
  • /login?logout: 注销成功后跳转到的页面。

由此可见,SpringSecurity默认有两个login,即登录页面和登录接口的地址都是 /login:

  • GET http://localhost:8080/login
  • POST http://localhost:8080/login

如果是GET 请求,表示你想访问登录页面;如果是 POST 请求,表示你想提交登录数据。

对于这几个URL接口,我们简单了解即可。

自定义表单认证配置

创建SecurityConfig配置类

我们先编写一个类,继承自WebSecurityConfigurerAdapter父类,该类的作用如下:

  • 验证所有请求;
  • 允许用户使用表达登录进行身份验证;
  • 允许用户使用Http基本认证
package com.lison.springsecurity.config.security;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;/*** @className: com.lison.springsecurity.config.security-> SecurityConfig* @description:* @author: Lison* @createDate: 2024-06-01*/@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {@Overrideprotected void configure(HttpSecurity http) throws Exception {//配置表单认证方式http.authorizeRequests().anyRequest().authenticated().and()//开启表单认证.formLogin();}
}

SecurityConfig类上添加@EnableWebSecurity注解后,会自动被Spring发现并注册。在configure()方法中,我执行了formLogin()方法,该方法的功能就是开启表单认证。

测试应用

启动项目,访问我们定义的/hello接口时,首先会重定向到/login页面。输入自己配置的用户名和密码后,才可以正常访问/hello接口。

在这里插入图片描述

当认证成功后,内部再次发生了302重定向:可见从/login接口重定向到了/hello接口。

自定义表单认证的登录界面

Spring Security一个特点就在于可以高度自定义,灵活配置,可以自定义一个登录页面。

服务端代码定义
package com.lison.springsecurity.config.security;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.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;/*** @className: com.lison.springsecurity.config.security-> SecurityConfig* @description:* @author: Lison* @createDate: 2024-06-01*/@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {/*** 用来定义哪些请求需要忽略安全控制,哪些请求必须接受安全控制;还可以在合适的时候清除SecurityContext以避免内存泄漏,* 同时也可以用来定义请求防火墙和请求拒绝处理器,另外我们开启Spring Security Debug模式也是这里配置的*/@Overridepublic void configure(WebSecurity web) throws Exception {//super.configure(web);web.ignoring().antMatchers("/js/**", "/css/**", "/images/**");}@Overrideprotected void configure(HttpSecurity http) throws Exception {//2.配置自定义的登录页面http.authorizeRequests().anyRequest().authenticated().and().formLogin()//加载自定义的登录页面地址.loginPage("/myLogin.html").permitAll().and()//注意:需禁用crsf防护功能,否则登录不成功.csrf().disable();}
}

1、WebSecurity执行流程

在这里插入图片描述

在configure(WebSecurity web)方法中,有个核心参数:WebSecurity类!在这个类里定义了一个securityFilterChainBuilders集合,可以同时管理多个SecurityFilterChain过滤器链,各位可以回顾我们学习Web基础时,关于过滤器的知识点,这些过滤器的执行是不是比Servlet更早?

当WebSecurity在执行时,会构建出一个名为 ”springSecurityFilterChain“Spring BeanFilterChainProxy代理类,它的作用是来 定义哪些请求可以忽略安全控制,哪些请求必须接受安全控制;以及在合适的时候 清除SecurityContext 以避免内存泄漏,同时也可以用来 定义请求防火墙和请求拒绝处理器,也可以在这里 开启Spring Security 的Debug模式

上面这一系列的Filter过滤器,我们就可以利用web.ignoring() 方法来配置想要忽略的静态资源 URL 地址,这样这些静态资源就可以不被拦截,从而可以被识别访问

2、HttpSecurity作用;

在这里插入图片描述

HttpSecurity用来构建包含一系列的过滤器链SecurityFilterChain,平常我们的配置就是围绕着这个SecurityFilterChain进行。

页面定义

首先自定义一个登陆页面,主要是编写html代码和css样式,其核心代码如下:

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Login Page</title><style>body {background-color: #f2f2f2;font-family: Arial, sans-serif;}.container {max-width: 400px;margin: 0 auto;padding: 40px;background-color: #fff;border-radius: 5px;box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);}h2 {text-align: center;margin-bottom: 30px;}.form-group {margin-bottom: 20px;}label {display: block;font-weight: bold;margin-bottom: 5px;}input[type="text"],input[type="password"] {width: 100%;padding: 10px;border: 1px solid #ccc;border-radius: 3px;}.btn {display: block;width: 100%;padding: 10px;background-color: #4caf50;color: #fff;font-weight: bold;text-align: center;text-decoration: none;border: none;border-radius: 3px;cursor: pointer;}.btn:hover {background-color: #45a049;}</style>
</head>
<body>
<div class="container"><h2>Login</h2><form action="/myLogin.html" method="post"><div class="form-group"><label for="username">Username:</label><input type="text" id="username" name="username" placeholder="Enter your username"></div><div class="form-group"><label for="password">Password:</label><input type="password" id="password" name="password" placeholder="Enter your password"></div><button class="btn" type="submit">Login</button></form>
</div>
</body>
</html>
测试应用

启动项目后,我们访问接口时,就会自动跳转到自己定义的/myLogin.html页面上,输入用户名和密码后,就可以成功访问自己的接口。
在这里插入图片描述

细化表单认证配置

修改表单认证页面中请求参数的名称,定义认证失败时的错误处理页面,处理退出登录时的操作等,这些都可以自定义配置,实现代码如下。

定义SecurityConfig类
package com.lison.springsecurity.config.security;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.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;/*** @className: com.lison.springsecurity.config.security-> SecurityConfig* @description:* @author: Lison* @createDate: 2024-06-01*/@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {/*** 用来定义哪些请求需要忽略安全控制,哪些请求必须接受安全控制;还可以在合适的时候清除SecurityContext以避免内存泄漏,* 同时也可以用来定义请求防火墙和请求拒绝处理器,另外我们开启Spring Security Debug模式也是这里配置的*/@Overridepublic void configure(WebSecurity web) throws Exception {//super.configure(web);web.ignoring().antMatchers("/js/**", "/css/**", "/images/**");}@Overrideprotected void configure(HttpSecurity http) throws Exception {//super.configure(http);//3.进一步配置自定义的登录页面   //拦截请求,创建FilterSecurityInterceptor http.authorizeRequests().anyRequest().authenticated()//用and来表示配置过滤器结束,以便进行下一个过滤器的创建和配置.and()//设置表单登录,创建UsernamePasswordAuthenticationFilter.formLogin().loginPage("/myLogin.html").permitAll()//指登录成功后,是否始终跳转到登录成功url。它默认为false.defaultSuccessUrl("/index.html",true)//post登录接口,登录验证由系统实现.loginProcessingUrl("/login")//用户密码错误跳转接口.failureUrl("/error.html")//要认证的用户参数名,默认username.usernameParameter("username")//要认证的密码参数名,默认password.passwordParameter("password").and()//配置注销.logout()//注销接口.logoutUrl("/logout")//注销成功后跳转到的接口.logoutSuccessUrl("/myLogin.html").permitAll()//删除自定义的cookie.deleteCookies("myCookie").and()//注意:需禁用crsf防护功能,否则登录不成功.csrf().disable();}
}
自定义登录页面

登录页面也跟着修改一下,主要是把form表单中action的值修改掉为 login

<body>
<div class="container"><h2>Login</h2><form action="/login" method="post"><div class="form-group"><label for="username">Username:</label><input type="text" id="username" name="username" placeholder="Enter your username"></div><div class="form-group"><label for="password">Password:</label><input type="password" id="password" name="password" placeholder="Enter your password"></div><button class="btn" type="submit">Login</button></form>
</div>
</body>

注意:此时form表单中action的值,要写成”/login“,因为我们在配置类中通过“loginProcessingUrl(“/login”)”方法中做了明确的配置

定义错误处理页面

输入了错误的用户名和密码后,可以提供一个错误处理页面,当认证失败后跳转到这个页面即可

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body>
<h1> ERROR 错误页面</h1>
</body>
</html>
测试验证

如果访问自己的接口,比如/hello,会先重定向到/myLogin.html页面,输入自己配置的用户名和密码,经过验证后,才会重定向到/index.html页面中,否则会重定向到我们配置的/error.html页面中。

1、重定向到/myLogin.html

访问资源时,会先重定向到自定义的登录页面。

在这里插入图片描述

2、重定向到/index.html

认证成功后,会重定向到index.html页面。

在这里插入图片描述

3、重定向到/error.html

认证失败后,会重定向到自定义的错误处理页面。

在这里插入图片描述

HTTP摘要认证

HTTP摘要认证简介

HTTP摘要认证和HTTP基本认证一样,也是在RFC2616中定义的一种认证方式,它的出现是为了弥补HTTP基本认证存在的安全隐患,但该认证方式也并不是很安全**。HTTP摘要认证会使用对通信双方来说都可知的口令进行校验,且最终以密文的形式来传输数据,所以相对于基本认证来说,稍微安全了一些。

HTTP摘要认证与基本认证类似,基于简单的“挑战-回应”模型。当发起一个未经认证的请求时,服务器会返回一个401回应,并给客户端返回与验证相关的参数,期待客户端依据这些参数继续做出回应,从而完成整个验证过程

HTTP摘要认证核心参数

服务端给客户端返回的验证相关参数如下:

  • username: 用户名。
  • password: 用户密码。
  • realm: 认证域,由服务器返回。
  • opaque: 透传字符串,客户端应原样返回。
  • method: 请求的方法。
  • nonce: 由服务器生成的随机字符串,包含过期时间(默认过期时间300s)和密钥。
  • nc: 即nonce-count,指请求的次数,用于计数,防止重放攻击。qop被指定时,nc也必须被指定。
  • cnonce: 客户端发给服务器的随机字符串,qop被指定时,cnonce也必须被指定。
  • qop: 保护级别,客户端根据此参数指定摘要算法。若取值为 auth,则只进行身份验证;若取值为auth-int,则还需要校验内容完整性,默认的qop为auth。
  • uri: 请求的uri。
  • response: 客户端根据算法算出的摘要值,这个算法取决于qop。
  • algorithm: 摘要算法,目前仅支持MD5。
  • entity-body: 页面实体,非消息实体,仅在auth-int中支持。

通常服务器端返回的数据包括realm、opaque、nonce、qop等字段,如果客户端需要做出验证回应,就必须按照一定的算法得到一些新的数据并一起返回**。在以上各种参数中,对服务器而言,最重要的字段是nonce;对客户端而言,最重要的字段是response**。

摘要认证代码实现

编写测试接口
package com.lison.springsecurity.controller;import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;/*** @className: com.lison.springsecurity.controller-> IndexController* @description:* @author: Lison* @createDate: 2024-06-01*/
@RestController
public class IndexController {@GetMapping("/admin/hello")public String helloAdmin() {return "hello, admin";}@GetMapping("/user/hello")public String helloUser() {return "hello, user";}@GetMapping("/visitor/hello")public String helloVisitor() {return "hello, visitor";}}
创建SecurityConfig配置类

这里比较重要的是配置摘要认证入口端点DigestAuthenticationEntryPoint

package com.lison.springsecurity.config.security;import com.lison.springsecurity.service.MyUserDetailsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
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.web.authentication.www.DigestAuthenticationEntryPoint;
import org.springframework.security.web.authentication.www.DigestAuthenticationFilter;/*** @className: com.lison.springsecurity.config.security-> SecurityConfig* @description:* @author: Lison* @createDate: 2024-06-01*/
@EnableWebSecurity(debug = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {@Autowiredprivate DigestAuthenticationEntryPoint digestAuthenticationEntryPoint;@Autowiredprivate MyUserDetailsService userDetailsService;//配置认证入口端点,主要是设置认证参数信息@Beanpublic DigestAuthenticationEntryPoint digestAuthenticationEntryPoint(){DigestAuthenticationEntryPoint point=new DigestAuthenticationEntryPoint();point.setKey("Security Demos");point.setRealmName("lison");point.setNonceValiditySeconds(500);return point;}public DigestAuthenticationFilter digestAuthenticationFilter(){DigestAuthenticationFilter filter=new DigestAuthenticationFilter();filter.setAuthenticationEntryPoint(digestAuthenticationEntryPoint);filter.setUserDetailsService(userDetailsService);return filter;}@Overrideprotected void configure(HttpSecurity http) throws Exception {http.authorizeRequests().antMatchers("/admin/**").hasRole("ADMIN").antMatchers("/user/**").hasRole("USER").antMatchers("/visitor/**").permitAll().anyRequest().authenticated().and().csrf().disable()//当未认证时访问某些资源,则由该认证入口类来处理..exceptionHandling().authenticationEntryPoint(digestAuthenticationEntryPoint).and()//添加自定义过滤器到过滤器链中.addFilter(digestAuthenticationFilter());}}
测试接口

访问一下需要认证的接口/admin/hello接口,这时候会发现浏览器弹出了一个用户名密码的认证窗口。然后我们在浏览器中可以看到HTTP摘要认证信息,realm是我们自定义的“lison”,qop是默认的“auth”方式。

在这里插入图片描述

由此可见,此时摘要认证的方式已经生效。

HTTP摘要认证弊端

HTTP摘要认证与HTTP基本认证一样,都是基于HTTP层面的认证方式,也不能使用Session对象,因而也不支持Remember-Me功能。该方式虽然解决了HTTP基本认证中以明文传输密码的问题,但并未解决密码明文存储的问题,所以依然有安全隐患,所以在开发中,摘要认证的方式也不怎么使用。

以上三种认证方式,我们需要重点掌握表单认证;

前后端分离时的安全处理方案

前后端分离简介

企业开发中,前后端分离已成为互联网项目开发的业界标准方式,其核心思想就是前端HTML页面通过AJAX,调用后端的RESTFUL API接口,并使用JSON数据进行交互****。

该方式可以有效的在前后端项目之间进行解耦,并且前后端分离会为以后的大型分布式架构、弹性计算架构、微服务架构、多端化服务(多种客户端,例如 浏览器,车载终端,安卓,IOS等)打下坚实的基础。

认证处理时的相关API

页面跳转的相关API

1、登录成功时的跳转API

  • defaultSuccessUrl
  • successForwardUrl

2、登录失败时的跳转API

  • failureUrl()
  • failureForwardUrl()
返回JSON格式的处理器

在前后端分离模式下,既然后端没有页面,页面都在前端,那就可以考虑使用JSON来进行信息交互了,我们把认证成功或认证失败的信息,以JSON的格式传递给前端,由前端来决定到底该往哪个页面跳转;

我们要返回JSON格式的信息,有如下相关方法:

  • successHandler()
  • failureHandler()
  • logoutSuccessHandler()
  • authenticationEntryPoint()

认证成功时的处理方案

相关的方法及其核心参数,即successHandler()和onAuthenticationSuccess参数。

1. successHandler()方法

successHandler()方法的功能十分强大,甚至也囊括了 defaultSuccessUrl()和 successForwardUrl() 的功能。

successHandler()方法的参数是一个 AuthenticationSuccessHandler 对象,这个对象中我们要实现的方法是 onAuthenticationSuccess()。

2. onAuthenticationSuccess参数

onAuthenticationSuccess() 方法中有三个参数,分别是:

  • HttpServletRequest: 利用该参数我们可以实现服务端的跳转;
  • HttpServletResponse: 利用该参数我们可以做客户端的跳转,也可以返回 JSON 数据;
  • Authentication: 这个参数则保存了我们刚刚登录成功的用户信息。
定义SecurityAuthenticationSuccessHandler类

r认证成功后需要处理的类,要实现AuthenticationSuccessHandler 接口

/*** 处理登录成功时的业务逻辑*/
public class SecurityAuthenticationSuccessHandler implements AuthenticationSuccessHandler {/*** Authentication:携带登录的用户名及角色等信息*/@Overridepublic void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws ServletException, IOException {//直接输出json格式的响应信息Object principal = authentication.getPrincipal();response.setContentType("application/json;charset=utf-8");PrintWriter out = response.getWriter();//以json格式对外输出身份信息out.write(new ObjectMapper().writeValueAsString(principal));out.flush();out.close();}
}
配置successHandler

在SecurityConfig配置类中,调用successHandler()方法,把前面定义的SecurityAuthenticationSuccessHandler类关联进来

@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {@Overrideprotected void configure(HttpSecurity http) throws Exception {http.authorizeRequests().anyRequest().authenticated().and().formLogin().permitAll()//认证成功时的处理器.successHandler(new SecurityAuthenticationSuccessHandler()).and().csrf().disable();}}
验证结果

我们进行登录验证,在认证成功后,就可以看到登录成功的用户信息是通过 JSON 返回到前端的,如下图所示:

在这里插入图片描述

Spring Security会把认证的用户信息以JSON格式展示出来,比如我们的用户名、密码、角色等信息。

认证失败时的处理方案

相关的API方法及参数。

failureHandler()

failureHandler()方法的参数是一个 AuthenticationFailureHandler 对象,这个对象中我们要实现的方法是 onAuthenticationFailure()。

onAuthenticationFailure()方法有三个参数,分别是:

  • HttpServletRequest: 利用该参数我们可以实现服务端的跳转;
  • HttpServletResponse: 利用该参数我们可以做客户端的跳转,也可以返回 JSON 数据;
  • AuthenticationException: 这个参数则保存了登录失败的原因。
代码实现

同样的,我们也要编写一个类SecurityAuthenticationFailureHandler,实现AuthenticationFailureHandler接口,来专门处理认证失败时的返回结果。

/*** 处理登录失败时的业务逻辑*/
public class SecurityAuthenticationFailureHandler  implements AuthenticationFailureHandler {/*** AuthenticationException:异常信息*/@Overridepublic void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException e) throws IOException, ServletException {//直接输出json格式的响应信息response.setContentType("application/json;charset=utf-8");PrintWriter out = response.getWriter();out.write(e.getMessage());out.flush();out.close();}
}
配置failureHandler

接着我们在SecurityConfig配置类中,调用failureHandler()方法来关联上面定义的SecurityAuthenticationFailureHandler类对象。

核心代码如下:

@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {@Overrideprotected void configure(HttpSecurity http) throws Exception {http.authorizeRequests().anyRequest().authenticated().and().formLogin().permitAll()//认证成功时的处理器.successHandler(new SecurityAuthenticationSuccessHandler())//认证失败时的处理器.failureHandler(new SecurityAuthenticationFailureHandler()).and().csrf().disable();}}
验证结果

配置完成后,我们再去登录,在认证失败时,就可以看到登录失败的用户信息通过 JSON 返回到前端了

在这里插入图片描述

退出登录时的处理方案

认证成功和认证失败后的处理方案后,退出登录后处理方案

1. logoutSuccessHandler()

负责退出登录的方法是logoutSuccessHandler(),这个方法中需要一个参数LogoutSuccessHandler;在LogoutSuccessHandler类中有一个方法 onLogoutSuccess(),该方法中的参数与登录成功时的参数一样。

2. 定义SecurityLogoutSuccessHandler类

我们先来定义一个SecurityLogoutSuccessHandler类,实现LogoutSuccessHandler接口,在这里负责输出退出登录时的JSON结果。

public class SecurityLogoutSuccessHandler implements LogoutSuccessHandler {@Overridepublic void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {response.setContentType("application/json;charset=utf-8");PrintWriter out = response.getWriter();out.write("注销成功");out.flush();out.close();}}
配置logoutSuccessHandler

然后我们在SecurityConfig配置类中,调用logoutSuccessHandler()方法来关联上面定义的SecurityLogoutSuccessHandler对象。

@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {@Overrideprotected void configure(HttpSecurity http) throws Exception {http.authorizeRequests().anyRequest().authenticated().and().formLogin().permitAll()//认证成功时的处理器.successHandler(new SecurityAuthenticationSuccessHandler())//认证失败时的处理器.failureHandler(new SecurityAuthenticationFailureHandler()).and().logout()//退出登录时的处理器.logoutSuccessHandler(new SecurityLogoutSuccessHandler()).and().csrf().disable();}}
验证结果

配置完成后,我们去访问/logout接口,退出登录成功,会有如下所示结果:

在这里插入图片描述

未认证时的处理方案

1. authenticationEntryPoint()

未认证时,同样有个专门的方法来处理,即authenticationEntryPoint()方法,这个方法中需要一个参数LoginUrlAuthenticationEntryPoint,在LoginUrlAuthenticationEntryPoint类中有一个方法 commence()。

2. 定义SecurityAuthenticationEntryPoint类

我们定义一个SecurityAuthenticationEntryPoint类,实现AuthenticationEntryPoint接口,在这里负责输出未认证时的JSON结果。

/*** @className: com.lison.springsecurity.config.security.handler-> SecurityAuthenticationEntryPoint* @description: 处理未登录认证时的响应信息* @author: Lison* @createDate: 2024-06-01*/
public class SecurityAuthenticationEntryPoint implements AuthenticationEntryPoint {@Overridepublic void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException {response.setContentType("application/json;charset=utf-8");PrintWriter out = response.getWriter();out.write("尚未登录,请先登录");out.flush();out.close();}}
配置authenticationEntryPoint

然后我们在SecurityConfig配置类中,调用authenticationEntryPoint()方法来关联上面定义的SecurityAuthenticationEntryPoint对象。

验证结果

配置完成后,我们在未登录时,直接去访问项目中的某个接口,就会看到未登录时返回的JSON信息,如下图所示:

在这里插入图片描述

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

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

相关文章

3.1、软件需求分析

软件需求分析 1、 需求分析定义及获取2、 需求分析过程2.1 需求提炼2.2 需求描述2.3 需求验证 3、 需求分析任务3.1 软件需求规格文档编制沟通活动通用任务集软件需求规格说明的原则软件需求规格说明的结构 1、 需求分析定义及获取 需求分析&#xff1a;确定系统必须具有的功能…

qt QStandardItemModel详解

1、概述 QStandardItemModel是Qt框架中提供的一个基于项的模型类&#xff0c;用于存储和管理数据&#xff0c;这些数据可以以表格的形式展示在视图控件&#xff08;如QTableView、QTreeView等&#xff09;中。QStandardItemModel支持丰富的数据操作&#xff0c;包括添加、删除…

Ubuntu18.04更换PREEMPT RT内核

文章目录 1 安装环境2 下载实时内核3 安装必要库和软件4 配置4.1 解压kernel压缩包4.2 进入kernel文件夹4.2.1 操作步骤4.2.2 修改配置文件 5 构建和安装6 启动显示内核选择界面7 启动界面选择实时内核版本进入8 uname -a查看操作系统内核信息 1 安装环境 Ubuntu 18.04原生内核…

立冬到了,选择Codigger暖心陪伴

立冬了&#xff0c;寒风渐起&#xff0c;但Codigger开发者们依然热情如火&#xff0c;编程的热情不会因为冬天而减退&#xff0c;相反&#xff0c;更加激情澎湃。就像立冬的清晨&#xff0c;虽然寒冷&#xff0c;却有着一种清新的气息&#xff0c;让我们一起迎接新的挑战&#…

全文检索ElasticSearch到底是什么?

学习ElasticSearch之前&#xff0c;我们先来了解一下搜索 1 搜索是什么 ① 概念&#xff1a;用户输入想要的关键词&#xff0c;返回含有该关键词的所有信息。 ② 场景&#xff1a; ​ 1互联网搜索&#xff1a;谷歌、百度、各种新闻首页&#xff1b; ​ 2 站内搜索&#xff…

Ansys Zemax | 手机镜头设计 - 第 4 部分:用LS-DYNA进行冲击性能分析

该系列文章将讨论智能手机镜头模组设计的挑战&#xff0c;从概念和设计到制造和结构变形分析。本文是四部分系列中的第四部分&#xff0c;它涵盖了相机镜头的显式动态模拟&#xff0c;以及对光学性能的影响。使用Ansys Mechanical和LS-DYNA对相机在地板上的一系列冲击和弹跳过程…

Follow软件的使用入门教程

开篇 看到很多兄弟还不知道怎么用这个当下爆火的浏览器&#xff01;在这里简单给需要入门的小伙伴一些建议&#xff1a; 介绍 简单解释一下&#xff0c;RSS 意思是简易信息聚合&#xff0c;用户可以通过 RSS 阅读器或聚合工具自主订阅并浏览各个平台的内容源&#xff0c;不用…

Redis数据库测试和缓存穿透、雪崩、击穿

Redis数据库测试实验 实验要求 1.新建一张user表&#xff0c;在表内插入10000条数据。 2.①通过jdbc查询这10000条数据&#xff0c;记录查询时间。 ②通过redis查询这10000条数据&#xff0c;记录查询时间。 3.①再次查询这一万条数据&#xff0c;要求根据年龄进行排序&#…

无root权限在Linux虚拟环境安装指定版本python

创建虚拟环境见 Linux创建虚拟环境&#xff0c;并在虚拟环境中运行项目_如何进入虚拟zhi环境再打开项目-CSDN博客 若使用python -m venv创建虚拟环境则无法指定python版本&#xff0c;需要单独安装 1.在官网Download Python | Python.org 下载对应版本的python包 例如我这里…

OCR、语音识别与信息抽取:免费开源的AI平台在医疗领域的创新应用

一、系统概述 在医疗行业中&#xff0c;大量数据来自手写病历、医学影像报告、患者对话记录等非结构化数据源。这些数据常常存在信息碎片化和管理困难的问题&#xff0c;给医务人员的工作带来了不便。思通数科AI多模态能力平台正是为了解决这一行业痛点而生&#xff0c;产品集…

Rust移动开发:Rust在iOS端集成使用介绍

iOS调用Rust 上篇介绍了 Rust移动开发&#xff1a;Rust在Android端集成使用介绍, 这篇主要看下iOS上如何使用Rust&#xff0c;Rust可以给移动端开发提供跨平台&#xff0c;通用组件支持。 该篇适合对iOS、Rust了解&#xff0c;想知道如何整合调用和编译的&#xff0c;如果想要…

「Mac畅玩鸿蒙与硬件24」UI互动应用篇1 - 灯光控制小项目

本篇将带领你实现一个互动性十足的灯光控制小项目&#xff0c;用户可以通过点击按钮来控制灯光的开关。该项目将涉及状态管理、动态图片加载以及按钮交互&#xff0c;是学习鸿蒙应用开发的重要基础。 关键词 UI互动应用状态管理动态图片加载用户交互 一、功能说明 在这个灯光…

什么是大模型?一文读懂大模型的基本概念

大模型是指具有大规模参数和复杂计算结构的机器学习模型。本文从大模型的基本概念出发&#xff0c;对大模型领域容易混淆的相关概念进行区分&#xff0c;并就大模型的发展历程、特点和分类、泛化与微调进行了详细解读&#xff0c;供大家在了解大模型基本知识的过程中起到一定参…

特力康|AI智能激光语音驱鸟器:精准识别,智能驱鸟,安全无忧

AI智能激光语音驱鸟器 随着电力设施的发展&#xff0c;鸟类侵扰问题逐渐引起了广泛关注。特别是在变电站等关键电力设施中&#xff0c;鸟类可能会导致设备短路、物理损害或系统故障&#xff0c;影响电网的稳定性。因此&#xff0c;亟需一种高效、无害的解决方案来解决这一问题…

变异凯撒(Crypto)

目录 解题思路 题目设计原理 总结 解题思路 从题目可以看出&#xff0c;这是凯撒密码&#xff0c;原理应该还是整体偏移&#xff0c;但是变异了。 凯撒密码只有字母的横移&#xff0c;而通过观察我们可知&#xff0c;加密密文包含大小写字母、特殊字符&#xff0c;于是猜想大…

SpringBoot在城镇住房保障系统中的应用案例

摘要 随着信息技术在管理上越来越深入而广泛的应用&#xff0c;管理信息系统的实施在技术上已逐步成熟。本文介绍了城镇保障性住房管理系统的开发全过程。通过分析城镇保障性住房管理系统管理的不足&#xff0c;创建了一个计算机管理城镇保障性住房管理系统的方案。文章介绍了城…

轻松实现无网络依赖:手把手教你如何在本地快速部署Llama3模型

我们利用 LM Studio 这款软件来可视化部署 Llama3。 [官网地址] 选择好对应的操作系统下载安装包&#xff0c;在下载好之后进行安装。在安装好之后我们就可以打开软件并使用了&#xff1a; 我们在中间的输入框部分输入 llama 来搜索并安装 llama 系列的模型&#xff0c;不过在…

物联网技术的智能监控

近年来&#xff0c;餐饮行业迅速发展&#xff0c;油烟肆意排放造成的环境污染愈加严重&#xff0c;有效监测、防控油烟问题迫在眉睫。对此&#xff0c;文章设计了一种基于物联网传感技术的油烟监控系统&#xff0c;考虑到餐饮行业使用需求&#xff0c;主控制器选择STM32单片机&…

【深度学习遥感分割|论文解读4】UNetFormer:一种类UNet的Transformer,用于高效的遥感城市场景图像语义分割

【深度学习遥感分割|论文解读4】UNetFormer&#xff1a;一种类UNet的Transformer&#xff0c;用于高效的遥感城市场景图像语义分割 【深度学习遥感分割|论文解读4】UNetFormer&#xff1a;一种类UNet的Transformer&#xff0c;用于高效的遥感城市场景图像语义分割 文章目录 【…

利用 Avalonia UI 构建 Blazor 混合应用程序

Blazor 是一个 .NET 前端框架&#xff0c;用于仅使用 .NET 技术构建 Web 应用程序。2021 年&#xff0c;Blazor 扩展到桌面端&#xff0c;推出了 Blazor Hybrid&#xff08;混合&#xff09;&#xff0c;使开发者可以在桌面平台上使用已有的技能。 Blazor 混合应用程序是传统的…