SpringBoot Spring Security的基本配置
Spring Boot针对Spring Security提供了自动化配置方案,因此可以使SpringSecurity非常容易地整合进Spring Boot项目中,这也是在Spring Boot项目中使用Spring Security的优势。
添加依赖:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency>
默认的用户名是user,默认的登录密码则在每次启动项目时随机生成,查看项目启动日志

配置用户名和密码:
可以在application.properties中配置默认的用户名、密码以及用户角色,配置方式如下
spring:
security:
user:
name: xc
password: 123456
roles: admin
当开发者在application.properties中配置了默认的用户名和密码后,再次启动项目,项目启动日志就不会打印出随机生成的密码了,用户可直接使用配置好的用户名和密码登录
基于内存的认证:
开发者也可以自定义类继承自WebSecurityConfigurerAdapter,进而实现对Spring Security更多的自定义配置,例如基于内存的认证,配置方式如下:
@Configuration
public class MyWebSecurityConfig extends WebSecurityConfigurerAdapter {
@Bean
PasswordEncoder passwordEncoder() {
return NoOpPasswordEncoder.getInstance();
}
// 配置用户
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("root").password("123").roles("ADMIN", "DBA")
.and()
.withUser("admin").password("123").roles("ADMIN", "USER")
.and()
.withUser("sang").password("123").roles("USER");
}
// 配置资源
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()// 调用authorizeRequests()方法开启HttpSecurity的配置
.antMatchers("/admin/**").hasRole("ADMIN")//表示用户访问“/admin/**”模式的URL必须具备ADMIN的角色
.antMatchers("/user/**").access("hasAnyRole('ADMIN','USER')")
.antMatchers("/db/**").access("hasRole('ADMIN') and hasRole('DBA')")
.anyRequest().authenticated()//表示除了前面定义的URL模式之外,用户访问其他的URL都必须认证后访问(登录后访问)
.and()
.formLogin()// 表示开启表单登录
.loginPage("/login_page")//这个login_page就是开发者自定义的登录页面,而不再是Spring Security提供的默认登录页。
.loginProcessingUrl("/login")//配置了登录接口为“/login”,配置loginProcessingUrl接口主要是方便Ajax或者移动端调用登录接口
.usernameParameter("name")//登录参数中用户名默认命名为username
.passwordParameter("passwd")//密码默认命名为password
.successHandler((req, resp, auth) -> {
/*
* 定义了登录成功的处理逻辑。用户登录成功后可以跳转到某一个页面,也可以返回一段JSON,这个要看具体业务逻辑,
* 本案例假设是第二种,用户登录成功后,返回一段登录成功的JSON。
* onAuthenticationSuccess方法的第三个参数Authentication一般用来获取当前登录用户的信息,
* 在登录成功后,可以获取当前登录用户的信息一起返回给客户端。
*/
resp.setContentType("application/json;charset=utf-8");
resp.setStatus(200);
Map<String, Object> map = new HashMap<>();
map.put("status", 200);
map.put("msg", auth.getPrincipal());
PrintWriter out = resp.getWriter();
out.write(new ObjectMapper().writeValueAsString(map));
out.flush();
out.close();
})
.failureHandler((req, resp, e) -> {
/*
* 定义了登录失败的处理逻辑,和登录成功类似,不同的是,登录失败的回调方法里有一个AuthenticationException参数,
* 通过这个异常参数可以获取登录失败的原因,进而给用户一个明确的提示。
*/
resp.setContentType("application/json;charset=utf-8");
resp.setStatus(401);
Map<String, Object> map = new HashMap<>();
map.put("status", 401);
if (e instanceof LockedException) {
map.put("msg", "账户被锁定,登录失败!");
} else if (e instanceof BadCredentialsException) {
map.put("msg", "账户名或密码输入错误,登录失败!" + e.getMessage());
} else if (e instanceof DisabledException) {
map.put("msg", "账户被禁用,登录失败!");
} else if (e instanceof AccountExpiredException) {
map.put("msg", "账户已过期,登录失败!");
} else if (e instanceof CredentialsExpiredException) {
map.put("msg", "密码已过期,登录失败!");
} else {
map.put("msg", "登录失败!");
}
PrintWriter out = resp.getWriter();
out.write(new ObjectMapper().writeValueAsString(map));
out.flush();
out.close();
})
.permitAll()// 最后还配置了permitAll,表示和登录相关的接口都不需要认证即可访问
.and()
.logout()//表示开启注销登录的配置
.logoutUrl("/logout")//表示配置注销登录请求URL为“/logout”,默认也是“/logout”
.clearAuthentication(true)//表示是否清除身份认证信息,默认为true,表示清除
.invalidateHttpSession(true)//表示是否使Session失效,默认为true
.addLogoutHandler((req, resp, auth) -> {
/*
* 配置一个LogoutHandler,开发者可以在LogoutHandler中完成一些数据清除工作,例如Cookie的清除
*/
})
.logoutSuccessHandler((req, resp, auth) -> resp.sendRedirect("/login_page"))// 配置一个LogoutSuccessHandler,开发者可以在这里处理注销成功后的业务逻辑,例如返回一段JSON提示或者跳转到登录页面等
.and().csrf().disable();//表示关闭csrf
}
}
多个HttpSecurity:
如果业务比较复杂,开发者也可以配置多个HttpSecurity,实现对WebSecurityConfigurerAdapter的多次扩展,代码如下
/**
* 配置多个HttpSecurity时,MultiHttpSecurityConfig不需要继承WebSecurityConfigurerAdapter,
* 在MultiHttpSecurityConfig中创建静态内部类继承WebSecurityConfigurerAdapter即可,
*/
@Configuration
/*
* 开发者也可以通过注解来灵活地配置方法安全,要使用相关注解,首先要通过@EnableGlobalMethodSecurity注解开启基于注解的安全配置
* prePostEnabled=true会解锁@PreAuthorize和@PostAuthorize两个注解,顾名思义,
* @PreAuthorize注解会在方法执行前进行验证,
* 而@PostAuthorize注解在方法执行后进行验证。
* securedEnabled=true会解锁@Secured注解。
*/
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
public class MultiHttpSecurityConfig {
@Bean
PasswordEncoder passwordEncoder() {
/*
* Spring Security提供了多种密码加密方案,官方推荐使用BCryptPasswordEncoder,
* BCryptPasswordEncoder使用BCrypt强哈希函数,开发者在使用时可以选择提供strength和SecureRandom实例。
* strength越大,密钥的迭代次数越多,密钥迭代次数为2^strength。strength取值在4~31之间,默认为10。
*/
return new BCryptPasswordEncoder(10);
}
@Autowired
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("root")
.password("$2a$10$RMuFXGQ5AtH4wOvkUqyvuecpqUSeoxZYqilXzbz50dceRsga.WYiq")
.roles("ADMIN", "DBA")
.and()
.withUser("admin")
.password("$2a$10$RMuFXGQ5AtH4wOvkUqyvuecpqUSeoxZYqilXzbz50dceRsga.WYiq")
.roles("ADMIN", "USER")
.and()
.withUser("sang")
.password("$2a$10$eUHbAOMq4bpxTvOVz33LIehLe3fu6NwqC9tdOcxJXEhyZ4simqXTC")
.roles("USER");
}
@Configuration
@Order(1) // 静态内部类上添加@Configuration注解和@Order注解,@Order注解表示该配置的优先级,数字越小优先级越大,未加@Order注解的配置优先级最小。
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("/login")
.usernameParameter("name")//登录参数中用户名默认命名为username
.passwordParameter("passwd")//密码默认命名为password
.permitAll()
.and()
.csrf()
.disable();
}
}
}
文章参考: Spring Boot+Vue全栈开发实战 - 10.1 Spring Security的基本配置

浙公网安备 33010602011771号