SpringBoot集成Spring Security
Spring Security是一个能够为基于Spring的企业应用系统提供声明式的安全访问控制解决方案的安全框架。
有两个作用:
- 认证:验证用户名和密码是否合法(是否系统中用户),这是第一关;
- 授权:是系统用户不代表你能使用某些功能,因为你可能没有权限,这是第二关;
Spring Security底层使用的是过滤器,针对url进行的拦截,对应到java中也就是类; 因此被称为粗粒度授权验证,就是验证url,你当前用户有没有这个url的权限。
1.新建一个springboot项目
2.引入Spring Security 依赖
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency>
3.新建一个controller测试访问
@RestController public class HelloController { @GetMapping("/hello") public String index(){ return "hello world!"; } }
4.运行项目:访问http://localhost:8080/hello
Spring Security默认给出用户名为user 密码为项目启动运行时生成的一串字符串如下图
当访问hello页面时,会默认跳转到login页面进行登录认证
认证成功会跳转到hello页面
5.Spring Security用户密码配置
1.springboot配置文件中添加配置
spring.security.user.name=admin
spring.security.user.password=123456
2.java代码在内存中配置用户
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder; @Configuration @EnableWebSecurity // 启用Spring Security的Web安全支持 public class SecurityConfig extends WebSecurityConfigurerAdapter { /** * 将用户设置在内存中 * * @param auth * @throws Exception */ @Autowired public void config(AuthenticationManagerBuilder auth) throws Exception { // 在内存中配置用户,配置多个用户调用`and()`方法 auth.inMemoryAuthentication() .passwordEncoder(passwordEncoder()) // 指定加密方式 .withUser("admin").password(passwordEncoder().encode("123456")).roles("ADMIN") .and().withUser("test").password(passwordEncoder().encode("123456")).roles("USER"); } @Bean public PasswordEncoder passwordEncoder() { // BCryptPasswordEncoder:Spring Security 提供的加密工具,可快速实现加密加盐 return new BCryptPasswordEncoder(); } }
3.从数据库获取账号,密码信息
6.登录处理和忽略拦截
@Controller public class IndexController { @GetMapping("/index") public String index(){ return "hello world !"; } @RequestMapping("login") public String showLogin(){ return "login.html"; } @GetMapping("/home") @ResponseBody public String home(){ return "欢迎来到主页!"; } }
@Configuration @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { /** * 将用户设置在内存中 * * @param auth * @throws Exception */ @Autowired public void config(AuthenticationManagerBuilder auth) throws Exception { // 在内存中配置用户,配置多个用户调用`and()`方法 auth.inMemoryAuthentication() // 指定加密方式 .passwordEncoder(passwordEncoder()) .withUser("admin").password(passwordEncoder().encode("123456")).roles("ADMIN") .and() .withUser("test").password(passwordEncoder().encode("123456")).roles("USER"); } @Bean public PasswordEncoder passwordEncoder() { // Spring Security 提供的密码加密工具,可快速实现加密加盐 return new BCryptPasswordEncoder(); } //登录配置 @Override protected void configure(HttpSecurity http) throws Exception { // 开启登录配置 http.authorizeRequests() // 标识访问 `/index` 这个接口,需要具备`ADMIN`角色 .antMatchers("/index").hasRole("ADMIN") // 允许匿名的url - 可理解为放行接口 - 多个接口使用,分割 .antMatchers("/", "/home").permitAll() // 其余所有请求都需要认证 .anyRequest().authenticated() .and() // 设置登录认证页面 .formLogin().loginPage("/login") // 登录成功后的处理接口 - 方式① .loginProcessingUrl("/home") // 自定义登陆用户名和密码属性名,默认为 username和password .usernameParameter("username") .passwordParameter("password") // 登录成功后的处理器 - 方式② // .successHandler((req, resp, authentication) -> { // resp.setContentType("application/json;charset=utf-8"); // PrintWriter out = resp.getWriter(); // out.write("登录成功..."); // out.flush(); // }) // 配置登录失败的回调 .failureHandler((req, resp, exception) -> { resp.setContentType("application/json;charset=utf-8"); PrintWriter out = resp.getWriter(); out.write("登录失败..."); out.flush(); }) .permitAll()//和表单登录相关的接口统统都直接通过 .and() .logout().logoutUrl("/logout") // 配置注销成功的回调 .logoutSuccessHandler((req, resp, authentication) -> { resp.setContentType("application/json;charset=utf-8"); PrintWriter out = resp.getWriter(); out.write("注销成功..."); out.flush(); }) .permitAll() .and() .httpBasic() .and() // 关闭CSRF跨域 .csrf().disable(); } //忽略拦截 @Override public void configure(WebSecurity web) throws Exception { // 设置拦截忽略url - 会直接过滤该url - 将不会经过Spring Security过滤器链 web.ignoring().antMatchers("/getUserInfo"); // 设置拦截忽略文件夹,可以对静态资源放行 web.ignoring().antMatchers("/css/**", "/js/**"); } }