1、spring security体验
只要加入spring security的依赖,项目中的所有接口都会被保护
org.springframework.boot
spring-boot-starter-security
访问任何接口都会跳转到/login上要求登陆,用户名为user,密码为控制台中给出的(Using generated security password: 954afb95-9d6c-4a55-93b4-844d60bc91de)
2、手工配置用户名密码
1) application.properties中配置
spring.security.user.name=user
spring.security.user.password=user
spring.security.user.roles=admin
2) java代码中配置(使用BCryptPasswordEncoder类进行密码加密)
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Bean
PasswordEncoder passwordEncoder(){
return NoOpPasswordEncoder.getInstance();//方法已过时
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()//基于内存的用户认证
.withUser("user").password("user").roles("user")
.and()
.withUser("admin").password("admin").roles("admin");
}
}
3、HttpSecurity配置(不同路径采用不同策略)
在SecurityConfig中重写configure(HttpSecurity http)方法
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/admin/**").hasRole("admin")//访问"/admin/**"路径下的请求需要admin权限
.antMatchers("/user/**").hasAnyRole("admin","user")//访问"/user/**"路径下的请求需要admin或者user权限
//.antMatchers("user/**").access("hasAnyRole('user','admin')")
.anyRequest().authenticated()//剩下的请求登陆后都可以访问
.and()
.formLogin()//表单登陆
.loginProcessingUrl("/doLogin")
.permitAll()//登陆接口可以直接访问
.and()
.csrf().disable();//关闭csrf
}
4、登陆表单详细配置(formLogin)
@Override
protected void configure(HttpSecurity http) throws Exception {
..........
.loginProcessingUrl("/doLogin")
.loginPage("/login")//登陆页面
.successHandler((request, response, authentication) -> {//(前后端分离方式)登陆成功处理 authentication保存登陆成功的用户信息
response.setContentType("application/json;charset=utf-8");
PrintWriter out = response.getWriter();
Map map = new HashMap<>();
map.put("status",200);
map.put("msg",authentication.getPrincipal());
out.write(new ObjectMapper().writeValueAsString(map));
out.flush();
out.close();
})
.failureHandler((request, response, exception) -> {//登陆失败处理
response.setContentType("application/json;charset=utf-8");
PrintWriter out = response.getWriter();
Map map = new HashMap<>();
map.put("status",401);
if (exception instanceof LockedException){
map.put("msg","账户被锁定,登陆失败");
}else if (exception instanceof BadCredentialsException){
map.put("msg","用户名或密码输入错误,登陆失败");
}else if (exception instanceof DisabledException){
map.put("msg","账户被禁用,登陆失败");
}else {//.....其他的异常AuthenticationException中查看
map.put("msg","登陆失败");
}
out.write(new ObjectMapper().writeValueAsString(map));
out.flush();
out.close();
})
.permitAll()//登陆接口可以直接访问
}
5、注销登录配置
@Override
protected void configure(HttpSecurity http) throws Exception {
..........
.and()
.logout()
.logoutUrl("/logout")
.logoutSuccessHandler((request, response, authentication) -> {
response.setContentType("application/json;charset=utf-8");
PrintWriter out = response.getWriter();
Map map = new HashMap<>();
map.put("status",200);
map.put("msg","注销登录成功");
out.write(new ObjectMapper().writeValueAsString(map));
out.flush();
out.close();
})
.and()
.csrf().disable();//关闭csrf
}
6、多个HttpSecurity配置
@Configuration
public class MultiHttpSecurityConfig {
@Bean
PasswordEncoder passwordEncoder(){
return NoOpPasswordEncoder.getInstance();
}
@Autowired
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()//基于内存的用户认证
.withUser("user").password("user").roles("user")
.and()
.withUser("admin").password("admin").roles("admin");
}
@Configuration
@Order(1)
public static class AdminSecurityConfig extends WebSecurityConfigurerAdapter{
@Override
protected void configure(HttpSecurity http) throws Exception {
http.antMatcher("/admin/**").authorizeRequests().anyRequest().hasRole("admin");
}
}
@Configuration
public static class OtherSecurityConfig extends WebSecurityConfigurerAdapter{
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().anyRequest().authenticated()
.and()
.formLogin()
.loginProcessingUrl("/doLogin")
.permitAll()
.and()
.csrf().disable();
}
}
}