springboot依靠security实现digest认证的实践

 更新时间:2025年09月28日 15:15:39   作者:knight郭志斌  
HTTP摘要认证通过加密参数(如nonce、response)验证身份,避免明文传输,但存在密码存储风险,相比基本认证更安全,却因实现复杂且不支持Remember-me,未被广泛采用,测试案例显示其工作流程

概述

HTTP 摘要认证使用对通信双方都可知的口令进行校验,最终的传输数据并非明文形式。

HTTP 摘要基本认证意在解决 HTTP 基本认证存在的大部分严重漏洞,但不应将其认为是Web安全的最终解决方案。

参数

HTTP摘要认证的回应与HTTP基本认证相比要复杂得多,下面看看HTTP摘要认证中涉及的一些参数:

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

通常服务器携带的数据包括realm、opaque、nonce、qop等字段,如果客户端需要做出验证回应,就必须按照一定的算法计算得到一些新的数据并一起返回。

总结:

  • HTTP摘要认证与HTTP基本认证一样,都是基于HTTP层面的认证方式,不使用session,因而不支持Remember-me。
  • 虽然解决了HTTP基本认证密码明文传输的问题,但并未解决密码明文存储的问题,依然存在安全隐患。
  • HTTP 摘要认证与 HTTP 基本认证相比,仅仅在非加密的传输层中有安全优势,但是其相对复杂的实现流程,使得它并不能成为一种被广泛使用的认证方式。

Demo

pom.xml依赖

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<!-- 测试包,当我们使用 mvn package 的时候该包并不会被打入,因为它的生命周期只在 test 之内-->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-security</artifactId>
		</dependency>

Digest1Application.java

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @author gzb
 */
@RestController
@SpringBootApplication
public class Digest1Application {

    public static void main(String[] args) {
        SpringApplication.run(Digest1Application.class, args);
    }

    @GetMapping("/demo1")
    public String demo1() {
        return "Hello battcn";
    }

}

MyPasswordEncoder.java

import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Component;

/**
 * @author gzb
 * @date 2021/10/1315:06
 */
@Component
public class MyPasswordEncoder implements PasswordEncoder {
    @Override
    public String encode(CharSequence charSequence) {
        return charSequence.toString();
    }

    @Override
    public boolean matches(CharSequence charSequence, String s) {
        return s.equals(charSequence.toString());
    }
}

WebSecurityConfig.java

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.core.userdetails.UserDetailsService;
import org.springframework.security.web.authentication.www.DigestAuthenticationEntryPoint;
import org.springframework.security.web.authentication.www.DigestAuthenticationFilter;

/**
 * @author gzb
 * @date 2021/10/1313:41
 */
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    @Autowired
    private DigestAuthenticationEntryPoint myDigestEntryPoint;
    @Autowired
    private UserDetailsService userDetailsService;

    @Bean
    public DigestAuthenticationEntryPoint digestEntryPoint() {
        DigestAuthenticationEntryPoint digestAuthenticationEntryPoint = new DigestAuthenticationEntryPoint();
        digestAuthenticationEntryPoint.setKey("https://blog.csdn.net/zhanwuguo8346");
        digestAuthenticationEntryPoint.setRealmName("spring security");
        digestAuthenticationEntryPoint.setNonceValiditySeconds(500);
        return digestAuthenticationEntryPoint;
    }

    public DigestAuthenticationFilter digestAuthenticationFilter() {
        DigestAuthenticationFilter filter = new DigestAuthenticationFilter();
        filter.setAuthenticationEntryPoint(myDigestEntryPoint);
        filter.setUserDetailsService(userDetailsService);
        return filter;
    }

    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .anyRequest().authenticated()
                .and()
                .csrf().disable()
                .exceptionHandling().authenticationEntryPoint(myDigestEntryPoint)
                .and()
                .addFilter(digestAuthenticationFilter());
    }
}

application.properties

server.port=9090
server.servlet.context-path=/ditest

spring.security.user.name=name
spring.security.user.password=password

测试

  • 浏览器F12打开开发者界面
  • 启动项目,浏览器访问:http://localhost:9090/ditest/demo1
  • 输入用户名、密码:name、password
  • 界面返回:Hello battcn

查看请求数据:

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • Java创建线程的五种写法总结

    Java创建线程的五种写法总结

    本文主要为大家详细介绍一下Java实现线程创建的五种写法,文中的示例代码讲解详细,对我们学习有一定的帮助,感兴趣的可以跟随小编学习一下
    2022-08-08
  • java语言中封装类代码示例

    java语言中封装类代码示例

    这篇文章主要介绍了java语言中封装类,涉及相关代码示例及结果分析,以及封装的好处简单介绍,具有一定借鉴价值,需要的朋友可以参考下
    2018-01-01
  • Java操作pdf的工具类itext的处理方法

    Java操作pdf的工具类itext的处理方法

    这篇文章主要介绍了Java操作pdf的工具类itext,iText是一种生成PDF报表的Java组件,通过在服务器端使用Jsp或JavaBean生成PDF报表,客户端采用超链接显示或下载得到生成的报表,需要的朋友可以参考下
    2022-04-04
  • JavaWeb利用邮箱帮用户找回密码

    JavaWeb利用邮箱帮用户找回密码

    这篇文章主要为大家详细介绍了JavaWeb利用邮箱帮用户找回密码,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2019-02-02
  • JPA中@ElementCollection使用示例详解

    JPA中@ElementCollection使用示例详解

    在JPA中,@ElementCollection注解主要用于映射集合属性,例如List、Set或数组等集合属性,以及Map结构的集合属性,每个属性值都有对应的key映射,这篇文章主要介绍了JPA中@ElementCollection使用,需要的朋友可以参考下
    2023-11-11
  • java中的反射及其优点说明

    java中的反射及其优点说明

    这篇文章主要介绍了java中的反射及其优点说明,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-05-05
  • JUnit4 Hamcrest匹配器常用方法总结

    JUnit4 Hamcrest匹配器常用方法总结

    这篇文章主要介绍了JUnit4 Hamcrest匹配器常用方法总结,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-11-11
  • SpringBoot基于Redis实现短信登录的操作

    SpringBoot基于Redis实现短信登录的操作

    验证码登录是非常常见的一种登录方式,能够简化用户登录的过程,本文主要介绍了SpringBoot基于Redis实现短信登录的操作,具有一定的参考价值,感兴趣的可以了解一下
    2023-12-12
  • JVM中ClassLoader类加载器的深入理解

    JVM中ClassLoader类加载器的深入理解

    这篇文章主要给大家介绍了关于JVM中ClassLoader类加载器的相关资料,文中通过图文介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-05-05
  • 使用Java实现MapReduce词频统计示例代码

    使用Java实现MapReduce词频统计示例代码

    这篇文章主要介绍了使用Java实现MapReduce词频统计的相关资料,通过词频统计示例来展示MapReduce的运行机制,涵盖了Mapper和Reducer的实现,并说明了如何配置和执行MapReduce作业,需要的朋友可以参考下
    2024-11-11

最新评论