开发者

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

目录
  • 概述
    • 参数
  • Demo
    • pom.XML依赖
    • Digest1Application.Java
    • MyPasswordEncoder.java
    • WebSecurityConfig.java
    • application.properties
    • 测试
  • 总结

    概述

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

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

    参数

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

    • username:用户名。
    • password:用户密码。
    • realm:认证域,由服务器返回。
    • opaque:透传字符串,客户端应原样返回。
    • methjavascriptod:请求的方法。
    • 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.SpringBootAppliandroidcation;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    /**
     * @author gzb
     */
    @RestphpController
    @SpringBootApplication
    public class Digest1Application {
    
        public static void main(String[] args) {
            SpringApplication.runphp(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 implandroidements 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

    查看请求数据:

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

    总结

    以上为个人经验,希望能给大家一个参考,也希望大家多多支持编程客栈(www.devze.com)。

    0

    上一篇:

    下一篇:

    精彩评论

    暂无评论...
    验证码 换一张
    取 消

    最新开发

    开发排行榜