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更多的自定义配置,例如基于内存的认证,配置方式如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 | @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的多次扩展,代码如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 | /** * 配置多个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的基本配置
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)