当前位置:   article > 正文

Spring Security 使用MD5加盐加密和BCrypt加密密码_md5加盐和bcrypt

md5加盐和bcrypt

之前我们都是使用MD5 Md5PasswordEncoder 或者SHA ShaPasswordEncoder 的哈希算法进行密码加密,在spring security中依然使用只要指定使用自定义加密算法就行,现在推荐spring使用的BCrypt BCryptPasswordEncoder,一种基于随机生成salt的根据强大的哈希加密算法。
一、MD5加密

package com.liuyanzhao.chuyun.util;
import java.security.MessageDigest;
/**
 * @author 言曌
 * @date 2018/2/9 下午6:11
 */
public class MD5Util {
    private static final String SALT = "liuyanzhao.com";
    /**
     * MD5加盐加密
     *
     * @param password
     * @return
     */
    public static String encode(String password) {
        password = password + SALT;
        MessageDigest md5 = null;
        try {
            md5 = MessageDigest.getInstance("MD5");
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        char[] charArray = password.toCharArray();
        byte[] byteArray = new byte[charArray.length];
        for (int i = 0; i < charArray.length; i++)
            byteArray[i] = (byte) charArray[i];
        byte[] md5Bytes = md5.digest(byteArray);
        StringBuffer hexValue = new StringBuffer();
        for (int i = 0; i < md5Bytes.length; i++) {
            int val = ((int) md5Bytes[i]) & 0xff;
            if (val < 16) {
                hexValue.append("0");
            }
            hexValue.append(Integer.toHexString(val));
        }
        return hexValue.toString();
    }
    public static void main(String[] args) {
        String hashPass = MD5Util.encode("123456");
        System.out.println(MD5Util.encode("123456"));//08dc78d36d1512e5a81ef05b01a37860
        System.out.println("08dc78d36d1512e5a81ef05b01a37860".equals(hashPass));//true
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43

所谓加盐加密,就是在原先密码上加点“盐”然后加密。因为虽然MD5加密是不可逆的,但是别人可以根据你的MD5密码不断比较发现你的原密码,比如你的密码设置得很简单是123456,加密后是 e10adc3949ba59abbe56e057f20f883e,一旦数据库泄露,密码丢失,不法分子很容易试探出来原密码。如果加上盐,只要别人不知道盐是什么,破解难度会提高很多。

二、BCrypt加密

package com.liuyanzhao.chuyun.util;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
/**
 * @author 言曌
 * @date 2018/2/22 下午8:39
 */
public class BCryptUtil {
    /**
     * 对密码进行加密
     * @param password
     * @return
     */
    public static String encode(String password) {
        BCryptPasswordEncoder bcryptPasswordEncoder = new BCryptPasswordEncoder();
        String hashPass = bcryptPasswordEncoder.encode(password);
        return hashPass;
    }
    /**
     * 对原密码和已加密的密码进行匹配,判断是否相等
     * @param password
     * @param encodedPassword
     * @return
     */
    public static boolean match(String password,String encodedPassword) {
        BCryptPasswordEncoder bcryptPasswordEncoder = new BCryptPasswordEncoder();
        boolean result = bcryptPasswordEncoder.matches(password, encodedPassword);
        return result;
    }
    public static void main(String[] args) {
        String hashPass = encode("123456");
        System.out.println(hashPass);
        System.out.println(match("123456",hashPass));//true
        System.out.println(match("123456","$2a$10$7wOQPHU2MfHt3X4wCFx5H.EZu.rlHMtY5HTFsqXiPd6BA5vNHJNf2"));//true
        System.out.println(match("123456","$2a$10$nYQWXcY.eVUwI8kYGtMCVOD0hWE4AKjzFg0oo91qc/ECQg/DD/CpS"));//true
        System.out.println(match("123456","$2a$10$9etIPtquQ3f..ACQkDHAVuBfjBoDXXWHHCOBl/RaJADxuXdSQB6I2"));//true
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37

使用 BCrypt 加密需要导入 Spring Security 的依赖。

我们发现每次运行都会得到不同的加密密码,但是这些加密后的密码都和 123456 相等。
三、Spring Security 使用 MD5 加密
SecurityConfig

package com.liuyanzhao.chuyun.config;
import com.liuyanzhao.chuyun.service.CustomUserService;
import com.liuyanzhao.chuyun.util.MD5Util;
import org.springframework.context.annotation.Bean;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
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.crypto.password.PasswordEncoder;
/**
 * 安全配置类
 *
 * @author 言曌
 * @date 2018/1/23 上午11:37
 */
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true) // 启用方法安全设置
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    private static final String KEY = "liuyanzhao.com";
    /**
     * 自定义用户Service验证
     * @return
     */
    @Bean
    CustomUserService customUserService() {
        return new CustomUserService();
    }
    /**
     * 核心配置
     * @param auth
     * @throws Exception
     */
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        DaoAuthenticationProvider authenticationProvider = new DaoAuthenticationProvider();
        authenticationProvider.setUserDetailsService(customUserService());
        //使用 MD5 加密
        auth.userDetailsService(customUserService()).passwordEncoder(new PasswordEncoder(){
            @Override
            public String encode(CharSequence rawPassword) {
                return MD5Util.encode((String)rawPassword);
            }
            @Override
            public boolean matches(CharSequence rawPassword, String encodedPassword) {
                return encodedPassword.equals(MD5Util.encode((String)rawPassword));
            }}); //user Details Service验证
        auth.authenticationProvider(authenticationProvider);
    }
    /**
     * 权限访问自定义配置
     */
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .antMatchers("/css/**", "/js/**","/","/fonts/**","/users").permitAll() // 都可以访问
                .antMatchers("/h2-console/**").permitAll() // 都可以访问
                .antMatchers("/admin/**").hasRole("ADMIN") // 需要相应的角色才能访问
                .antMatchers("/console/**").hasAnyRole("ADMIN","USER") // 需要相应的角色才能访问
                .and()
                .formLogin()   //基于 Form 表单登录验证
                .loginPage("/login") //登录页面
                .failureUrl("/login?error=true") // 登录错误页面
                .and().logout()
                .and().rememberMe().key(KEY) // 启用 remember me
                .tokenValiditySeconds(1209600)//记住两周
                .and().exceptionHandling().accessDeniedPage("/403");  // 处理异常,拒绝访问就重定向到 403 页面
        http.csrf().ignoringAntMatchers("/h2-console/**"); // 禁用 H2 控制台的 CSRF 防护
        http.headers().frameOptions().sameOrigin(); // 允许来自同一来源的H2 控制台的请求
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72

这里的 MD5Util 可以直接用上面的第一步里的
四、Spring Security 使用 BCrypt 加密
SecurityConfig

package com.liuyanzhao.chuyun.config;
import com.liuyanzhao.chuyun.service.CustomUserService;
import org.springframework.context.annotation.Bean;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
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.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
/**
 * 安全配置类
 *
 * @author 言曌
 * @date 2018/1/23 上午11:37
 */
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true) // 启用方法安全设置
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    private static final String KEY = "liuyanzhao.com";
    /**
     * 自定义用户Service验证
     * @return
     */
    @Bean
    CustomUserService customUserService() {
        return new CustomUserService();
    }
    /**
     * 使用使用 BCrypt加密
     * @return
     */
    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();   // 使用 BCrypt 加密
    }
    /**
     * 核心配置
     * @param auth
     * @throws Exception
     */
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        DaoAuthenticationProvider authenticationProvider = new DaoAuthenticationProvider();
        authenticationProvider.setUserDetailsService(customUserService());
        authenticationProvider.setPasswordEncoder(passwordEncoder());
        auth.authenticationProvider(authenticationProvider);
    }
    /**
     * 权限访问自定义配置
     */
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .antMatchers("/css/**", "/js/**","/","/fonts/**","/users").permitAll() // 都可以访问
                .antMatchers("/h2-console/**").permitAll() // 都可以访问
                .antMatchers("/admin/**").hasRole("ADMIN") // 需要相应的角色才能访问
                .antMatchers("/console/**").hasAnyRole("ADMIN","USER") // 需要相应的角色才能访问
                .and()
                .formLogin()   //基于 Form 表单登录验证
                .loginPage("/login") //登录页面
                .failureUrl("/login?error=true") // 登录错误页面
                .and().logout()
                .and().rememberMe().key(KEY) // 启用 remember me
                .tokenValiditySeconds(1209600)//记住两周
                .and().exceptionHandling().accessDeniedPage("/403");  // 处理异常,拒绝访问就重定向到 403 页面
        http.csrf().ignoringAntMatchers("/h2-console/**"); // 禁用 H2 控制台的 CSRF 防护
        http.headers().frameOptions().sameOrigin(); // 允许来自同一来源的H2 控制台的请求
    }
}
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72

最后,还是建议使用 BCrypt 加密,更安全,但是密码字段长度至少要60位。

【转载出自】https://liuyanzhao.com/7569.html

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/神奇cpp/article/detail/921953
推荐阅读
相关标签
  

闽ICP备14008679号