部分引自 www.javaboy.org
比如MD5,但MD5不是很安全,因?yàn)樗麄儾杉用軙r(shí),相同的密碼產(chǎn)生的密文都是一樣的,并不是特別安全,所以可以給密碼加一些鹽,相同的密碼加一些鹽,“味道”又不一樣了,鹽可以采取隨機(jī)數(shù)、用戶名或其他方式,但始終要維護(hù)一個(gè)鹽字段,在Security中給我提供了另一種手段(BCryptPasswordEncoder),令相同的密碼差生的密文每次都是不一樣的
我們啟動(dòng)一個(gè)單元測試產(chǎn)生一些密文
@RunWith(SpringRunner.class)
@SpringBootTest
public class SecurityApplicationTests {
@Test
public void contextLoads() {
BCryptPasswordEncoder bc = new BCryptPasswordEncoder();
for (int i = 0; i < 10; i++) {
System.out.println(bc.encode("123"));
}
}
}

image.png
修改SecurityConfig
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("yzn").password("$2a$10$WuUO9k/3LfTGzMEAKxNtAenttd9ulTq7wTj17ojqbU44Q5rwN/mWu").roles("admin")
.and()
.withUser("test").password("$2a$10$WuUO9k/3LfTGzMEAKxNtAenttd9ulTq7wTj17ojqbU44Q5rwN/mWu").roles("user");
}
@Bean
PasswordEncoder passwordEncoder(){
return new BCryptPasswordEncoder();
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/admin/**").hasRole("admin")
.antMatchers("/user/**").hasAnyRole("admin", "user")
.anyRequest().authenticated()
.and()
.formLogin()
// 登錄處理接口
.loginProcessingUrl("/doLogin")
// 定義登錄頁面,未登錄時(shí),訪問一個(gè)需要登錄之后才能訪問的接口,會(huì)自動(dòng)跳轉(zhuǎn)到該頁面
.loginPage("/login")
//定義登錄時(shí),用戶名的 key,默認(rèn)為 username
.usernameParameter("uname")
//定義登錄時(shí),用戶密碼的 key,默認(rèn)為 password
.passwordParameter("passwd")
//登錄成功的處理器
.successHandler(new AuthenticationSuccessHandler() {
@Override
public void onAuthenticationSuccess(HttpServletRequest req, HttpServletResponse res, Authentication authentication) throws IOException, ServletException {
res.setContentType("application/json;charset=utf-8");
PrintWriter out = res.getWriter();
Map<String,Object> map = new HashMap();
map.put("status", 200);
// authentication.getPrincipal() 可以把登錄者信息取出來
map.put("msg", authentication.getPrincipal());
out.write(new ObjectMapper().writeValueAsString(map));
out.flush();
}
})
.failureHandler(new AuthenticationFailureHandler() {
@Override
public void onAuthenticationFailure(HttpServletRequest req, HttpServletResponse res, AuthenticationException e) throws IOException, ServletException {
res.setContentType("application/json;charset=utf-8");
PrintWriter out = res.getWriter();
Map<String,Object> map = new HashMap();
map.put("status", 200);
map.put("msg", "failed");
out.write(new ObjectMapper().writeValueAsString(map));
out.flush();
}
})
//和表單登錄相關(guān)的接口統(tǒng)統(tǒng)都直接通過
.permitAll()
.and()
.logout()
.logoutUrl("/logout")
.logoutSuccessHandler(new LogoutSuccessHandler() {
@Override
public void onLogoutSuccess(HttpServletRequest req, HttpServletResponse res, Authentication authentication) throws IOException, ServletException {
res.setContentType("application/json;charset=utf-8");
PrintWriter out = res.getWriter();
Map<String,Object> map = new HashMap();
map.put("status", 200);
map.put("msg", "注銷登錄成功");
out.write(new ObjectMapper().writeValueAsString(map));
out.flush();
}
})
.and()
.csrf().disable();
}
}
測試是否可以登錄