千家信息网

Spring Boot中如何实现HTTP认证

发表于:2025-01-25 作者:千家信息网编辑
千家信息网最后更新 2025年01月25日,这篇文章将为大家详细讲解有关Spring Boot中如何实现HTTP认证,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。HttpBasic 认证有一定的
千家信息网最后更新 2025年01月25日Spring Boot中如何实现HTTP认证

这篇文章将为大家详细讲解有关Spring Boot中如何实现HTTP认证,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。

HttpBasic 认证有一定的局限性与安全隐患,因此在实际项目中使用并不多,但是,有的时候为了测试方便,开启 HttpBasic 认证能方便很多。

今天还是来和大家简单聊一聊 Spring Security 中的 HttpBasic 认证。

1.什么是 HttpBasic

Http Basic 认证是 Web 服务器和客户端之间进行认证的一种方式,最初是在 HTTP1.0 规范(RFC 1945)中定义,后续的有关安全的信息可以在 HTTP 1.1 规范(RFC 2616)和 HTTP 认证规范(RFC 2617)中找到。

HttpBasic 最大的优势在于使用非常简单,没有复杂的页面交互,只需要在请求头中携带相应的信息就可以认证成功,而且它是一种无状态登录,也就是 session 中并不会记录用户的登录信息。

HttpBasic 最大的问题在于安全性,因为用户名/密码只是简单的通过 Base64 编码之后就开始传送了,很容易被工具嗅探到,进而暴露用户信息。

Spring Security 中既支持基本的 HttpBasic 认证,也支持 Http 摘要认证,Http 摘要认证是在 HttpBasic 认证的基础上,提高了信息安全管理,但是代码复杂度也提高了不少,所以 Http 摘要认证使用并不多。

这里,和大家分享 Spring Security 中的这两种认证方式。

2.HttpBasic 认证

我们先来看实现,再来分析它的认证流程。

首先创建一个 Spring Boot 项目,引入 Web 和 Spring Security 依赖,如下:

接下来创建一个测试接口:

@RestController
public class HelloController {
@GetMapping("/hello")
public String hello() {
return "hello";
}
}

再开启 HttpBasic 认证:

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.anyRequest().authenticated()
.and()
.httpBasic();
}
}

最后再在 application.properties 中配置基本的用户信息,如下:

spring.security.user.password=123
spring.security.user.name=javaboy

配置完成后,启动项目,访问 /hello 接口,此时浏览器中会有弹出框,让我们输入用户名/密码信息:

此时我们查看请求响应头,如下:

可以看到,浏览器响应了 401,同时还携带了一个 WWW-Authenticate 响应头,这个是用来描述认证形式的,如果我们使用的是 HttpBasic 认证,默认响应头格式如图所示。

接下来我们输入用户名密码,点击 Sign In 进行登录,登录成功后,就可以成功访问到 /hello 接口了。

我们查看第二次的请求,如下:

大家可以看到,在请求头中,多了一个 Authorization 字段,该字段的值为 Basic amF2YWJveToxMjM=,

amF2YWJveToxMjM= 是一个经过 Base64 编码之后的字符串,我们将该字符串解码之后发现,结果如下:

String x = new String(Base64.getDecoder().decode("amF2YWJveToxMjM="), "UTF-8");

解码结果如下:

可以看到,这就是我们的用户名密码信息。用户名/密码只是经过简单的 Base64 编码之后就开始传递了,所以说,这种认证方式比较危险。

我们再来稍微总结一下 HttpBasic 认证的流程:

  1. 浏览器发出请求,说要访问 /hello 接口。

  2. 服务端返回 401,表示未认证。同时在响应头中携带 WWW-Authenticate 字段来描述认证形式。

  3. 浏览器收到 401 响应之后,弹出对话框,要求用户输入用户名/密码,用户输入完用户名/密码之后,浏览器会将之进行 Base64 编码,编码完成后,发送到服务端。

  4. 服务端对浏览器传来的信息进行解码,并校验,当没问题的时候,给客户端作出响应。

大致的流程就是这样。

3.Http 摘要认证

Http 摘要认证与 HttpBasic 认证基本兼容,但是要复杂很多,这个复杂不仅体现在代码上,也体现在请求过程中。

Http 摘要认证最重要的改进是他不会在网络上发送明文密码。它的整个认证流程是这样的:

  1. 浏览器发出请求,说要访问 /hello 接口。

  2. 服务端返回 401,表示未认证,同时在响应头中携带 WWW-Authenticate 字段来描述认证形式。不同的是,这次服务端会计算出一个随机字符串,一同返回前端,这样可以防止重放攻击(所谓重放攻击就是别人嗅探到你的摘要信息,把摘要当成密码一次次发送服务端,加一个会变化的随机字符串,生成的摘要信息就会变化,就可以防止重放攻击),如下:

同时,服务端返回的字段还有一个 qop,表示保护级别,auth 表示只进行身份验证;auth-int 表示还要校验内容。

nonce 是服务端生成的随机字符串,这是一个经过 Base64 编码的字符串,经过解码我们发现,它是由过期时间和密钥组成的。在以后的请求中 nonce 会原封不动的再发回给服务端。

  1. 客户端选择一个算法,根据该算法计算出密码以及其他数据的摘要,如下:

可以看到,客户端发送到服务端的数据比较多。

  • nonce 就是服务端发来的随机字符串。

  • response 是生成的摘要信息。

  • nc 表示请求此时,可以防止重放攻击。

  • cnonce 表示客户端发送给服务端的随机字符串。

  1. 服务端根据客户端发送来的用户名,可以查询出用户密码,再根据用户密码可以计算出摘要信息,再将摘要信息和客户端发送来的摘要信息进行对比,就能确认用户身份。

这就是整个流程。

一言以蔽之,原本的用户密码被摘要信息代替了,为了安全,摘要信息会根据服务端返回的随机字符串而发生变化,服务端根据用户密码,同样算出密码的摘要信息,再和客户端传来的摘要信息进行对比,没问题的话,用户就算认证成功了。当然,在此基础上还加了一些过期限制、重放攻击防范机制等。

好了,那这个在 Spring Security 代码中该怎么实现呢?

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.anyRequest().authenticated()
.and()
.csrf()
.disable()
.exceptionHandling()
.authenticationEntryPoint(digestAuthenticationEntryPoint())
.and()
.addFilter(digestAuthenticationFilter());
}

@Bean
DigestAuthenticationEntryPoint digestAuthenticationEntryPoint() {
DigestAuthenticationEntryPoint entryPoint = new DigestAuthenticationEntryPoint();
entryPoint.setKey("javaboy");
entryPoint.setRealmName("myrealm");
entryPoint.setNonceValiditySeconds(1000);
return entryPoint;
}
@Bean
DigestAuthenticationFilter digestAuthenticationFilter() {
DigestAuthenticationFilter filter = new DigestAuthenticationFilter();
filter.setAuthenticationEntryPoint(digestAuthenticationEntryPoint());
filter.setUserDetailsService(userDetailsService());
return filter;
}

@Override
@Bean
protected UserDetailsService userDetailsService() {
InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager();
manager.createUser(User.withUsername("javaboy").password("123").roles("admin").build());
return manager;
}

@Bean
PasswordEncoder passwordEncoder() {
return NoOpPasswordEncoder.getInstance();
}

}

配置无非就是两方面,一方面是服务端随机字符串的生成,另一方面就是客户端摘要信息的校验。

  1. 首先提供 DigestAuthenticationEntryPoint 的实例,配置服务端随机数生成的一些参数,例如 nonce 有效期(多长时间会变),realm 的名字,以及生成 nonce 时所需要的 key。nonce 的具体生成逻辑在 DigestAuthenticationEntryPoint#commence 方法中:

public void commence(HttpServletRequest request, HttpServletResponse response,
AuthenticationException authException) throws IOException {
HttpServletResponse httpResponse = response;
long expiryTime = System.currentTimeMillis() + (nonceValiditySeconds * 1000);
String signatureValue = DigestAuthUtils.md5Hex(expiryTime + ":" + key);
String nonceValue = expiryTime + ":" + signatureValue;
String nonceValueBase64 = new String(Base64.getEncoder().encode(nonceValue.getBytes()));
String authenticateHeader = "Digest realm=\"" + realmName + "\", "
+ "qop=\"auth\", nonce=\"" + nonceValueBase64 + "\"";
if (authException instanceof NonceExpiredException) {
authenticateHeader = authenticateHeader + ", stale=\"true\"";
}
if (logger.isDebugEnabled()) {
logger.debug("WWW-Authenticate header sent to user agent: "
+ authenticateHeader);
}
httpResponse.addHeader("WWW-Authenticate", authenticateHeader);
httpResponse.sendError(HttpStatus.UNAUTHORIZED.value(),
HttpStatus.UNAUTHORIZED.getReasonPhrase());
}

在这段代码中,首先获取到过期时间,然后给过期时间和 key 一起计算出消息摘要,再将 nonce 和消息摘要共同作为 value,计算出一个 Base64 编码字符,再将该编码字符写回到前端。

  1. 配置 DigestAuthenticationFilter 过滤器,主要用来处理前端请求。过滤器的源码比较长,我这里就不贴出来了,一个核心的思路就是从前端拿到用户请求的摘要信息,服务端也根据一直的信息算出来一个摘要,再根据传过来的摘要信息进行比对,进而确认用户身份。

配置完成后,重启服务端进行测试。

测试效果其实和 HttpBasic 认证是一样的,所有的变化,只是背后的实现有所变化而已,用户体验是一样的。

4.小结

Http 摘要认证的效果虽然比 HttpBasic 安全,但是其实大家看到,整个流程下来解决的安全问题其实还是非常有限。而且代码也麻烦了很多,因此这种认证方式并未广泛流行开来。

Http 认证小伙伴们作为一个了解即可,里边的有一些思想还是挺有意思的,可以激发我们解决其他问题的思路,例如对于重放攻击的的解决办法,我们如果想自己防御重放攻击,就可以参考这里的实现思路。

关于Spring Boot中如何实现HTTP认证就分享到这里了,希望以上内容可以对大家有一定的帮助,可以学到更多知识。如果觉得文章不错,可以把它分享出去让更多的人看到。

认证 摘要 信息 用户 服务 密码 字符 字符串 客户 客户端 用户名 编码 安全 就是 浏览器 攻击 浏览 生成 流程 配置 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 数据库select 什么意思 伟仕佳杰和网络安全龙头 网络安全运维专业工程师 衡阳网络安全培训机构学历要求低 安卓app怎样实现服务器控制 服务器能装window10吗 来宾青年讲师网络安全培训 浙江服务器电源哪里便宜 联想服务器rd630 服务器内存条怎么分别第几代 数据库实验六 系统安全管理 小程序的软件开发多少算合理 数据库第一列自增 工业网关和服务器通信 互联网金融信息科技 远程连接家用服务器 代理服务器手机怎么加入 语音转文字服务器异常 软件开发用什么品牌电脑 数据库事务的原则 江汉靠谱的软件开发中心 前程软件开发公司云南昆明 幼儿园网络安全教育美篇 篮球赛果数据库 数据库基础及应用章节答案 内蒙算力服务器租赁费用 汛期网络安全保障工作报道 南昌网络安全培训机构线上学习 研究报告在哪些数据库 网络安全 工控安全公司
0