赞
踩
之前我们都是使用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位。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。