Spring Security 使用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
    }
}

所谓加盐加密,就是在原先密码上加点“盐”然后加密。因为虽然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
    }
}

使用 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 控制台的请求
    }
}

这里的 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 控制台的请求
    }
}
 

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

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

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值