部分引自 www.javaboy.org
比如MD5,但MD5不是很安全,因为他们采加密时,相同的密码产生的密文都是一样的,并不是特别安全,所以可以给密码加一些盐
,相同的密码加一些盐,“味道”又不一样了,盐可以采取随机数、用户名或其他方式,但始终要维护一个盐字段,在Security中给我提供了另一种手段(BCryptPasswordEncoder),令相同的密码差生的密文每次都是不一样的
我们启动一个单元测试产生一些密文
@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"));
}
}
}
修改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")
// 定义登录页面,未登录时,访问一个需要登录之后才能访问的接口,会自动跳转到该页面
.loginPage("/login")
//定义登录时,用户名的 key,默认为 username
.usernameParameter("uname")
//定义登录时,用户密码的 key,默认为 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();
}
})
//和表单登录相关的接口统统都直接通过
.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();
}
}
测试是否可以登录