SpringBoot整合SpringSecurity学习笔记 SpringSecurity入门

SpringBoot整合SpringSecurity(入门)

Spring Security是一个功能强大且高度可定制的身份验证和访问控制框架。它是用于保护基于Spring的应用程序的实际标准。
Spring Security是一个框架,致力于为Java应用程序提供身份验证和授权。像所有Spring项目一样,Spring Security的真正强大之处在于可以轻松扩展以满足自定义要求

官方文档参考

  • 在pom.xml中加入我们SpringSecurity依赖

 		
            org.springframework.boot</groupId>
            spring-boot-starter-security</artifactId>
        </dependency>
  • 在application.properties配置端口

server.port=8086
  • 写一个简单的controller

@RestController
@RequestMapping("/user")
public class UserController {

    @RequestMapping("/hello")
    public String hello(){
        return "Hello SpringSecurity!";
    }
}
  • 启动项目,启动成功后直接访问 localhost:8086/user/hello会自动重定向到了登录的界面:SpringBoot整合SpringSecurity学习笔记 SpringSecurity入门_第1张图片

当你看到这个登陆页面时,说明你在SpringBoot中整合SpringSecurity已经成功了
但是我们并没有在项目中设置用户名和密码 ,也没有写 /login ;但是别忘了我们引入了SpringSecurity, 如果我们没有进行SpringSecurity配置的话,它在启动时就会默认配置(源码截图如下)
SpringBoot整合SpringSecurity学习笔记 SpringSecurity入门_第2张图片
默认用户名 user ,查看我们启动日志SpringSecurity还随机生成了一串密码:
在这里插入图片描述
输入用户名和密码:
SpringBoot整合SpringSecurity学习笔记 SpringSecurity入门_第3张图片
我们成功访问到 /user/hello
在这里插入图片描述

  • 自己配置用户及密码

1.配置文件配置:

注: 配置文件配置的用户名和密码始终是通过 set 方法注入到属性中去
SpringBoot整合SpringSecurity学习笔记 SpringSecurity入门_第4张图片

spring.security.user.name=zcc
spring.security.user.password=123

重启项目,输入我们自定义的用户名和密码,也成功访问到 /user/hello 在这里插入图片描述

2.java配置类配置:

自定义一个 Spring Security 的配置类,继承 WebSecurityConfigurerAdapter 类:

重写 configure(AuthenticationManagerBuilder auth) 方法,配置用户名,密码,角色

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Bean
    PasswordEncoder passwordEncoder(){
        return NoOpPasswordEncoder.getInstance();//不加密
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication().withUser("zhangsan").password("123");
    }
}

重启项目后,通过上面用户和密码也可成功访问到 /user/hello

通过上面自定义配置类也可以为用户配置角色及配置多用户 :

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication() //开启在内存中定义用户
        .withUser("zhangsan").password("123").roles("admin") //用户名 密码 角色
        .and() //配置多个用户,用 and 相连
        .withUser("zhangsan2").password("123").roles("user");
    }

重写 configure(WebSecurity web) 来配置忽略掉的 URL 地址,一般是配置忽略静态文件 :

	@Override
	public void configure(WebSecurity web) throws Exception {
	    web.ignoring().antMatchers("/js/**", "/css/**","/images/**");
	}

然后我们改造一下我们的 UserController 方便我们测试配置的用户角色 :

@RestController
@RequestMapping("/user")
public class UserController {

    @RequestMapping("/hello")
    public String hello(){
        return "Hello SpringSecurity!";
    }

    @RequestMapping("/admin")
    public String admin(){
        return "你有admin角色";
    }

    @RequestMapping("/user")
    public String user(){
        return "你有user角色";
    }
}

重写 configure(HttpSecurity http) 进行登陆配置

 @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests() //授权配置(启用基于 HttpServletRequest 的访问限制,开始配置哪些URL需要被保护、哪些不需要被保护)
                .antMatchers("/admin/**").hasRole("admin") //配置/admin/**接口,拥有admin角色的可访问
                .antMatchers("/user/**").hasRole("user")  //配置/user/**接口,拥有user角色的可访问
                .and().formLogin();
    }

重启项目,我们用拥有 admin 角色的用户: zhangsan 登陆访问 /admin/hello/hello 都访问成功在这里插入图片描述在这里插入图片描述
访问 /user/hello 看到这个在这里插入图片描述
表明他没有这个访问权限,同理用户: zhangsan2 ,也是不能访问 /admin/hello
但是如果做前后端分离,用postman测试,如果我们的请求方式不是 get 请求时,也会给我们报 403SpringBoot整合SpringSecurity学习笔记 SpringSecurity入门_第5张图片
然后我百度了一下,说的是从Spring Security 4.0开始,默认情况下会启用CSRF保护,以防止CSRF攻击应用程序,Spring Security CSRF会针对PATCH,POST,PUTDELETE方法进行防护。
然后我们 禁用CSRF保护

 @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests() //授权配置(启用基于 HttpServletRequest 的访问限制,开始配置哪些URL需要被保护、哪些不需要被保护)
                .antMatchers("/admin/**").hasRole("admin") //配置/admin/**接口,拥有admin角色的可访问
                .antMatchers("/user/**").hasRole("user") //配置/user/**接口,拥有user角色的可访问
                .and().formLogin()
                .and().csrf().disable() ; //禁用CSRF保护(支持跨域)
    }

重启项目,用postman 登陆后就可以正常访问了在这里插入图片描述SpringBoot整合SpringSecurity学习笔记 SpringSecurity入门_第6张图片
但是登陆成功后我们会发现给我们返回了 404
SpringBoot整合SpringSecurity学习笔记 SpringSecurity入门_第7张图片
为什么会出现这种情况呢?肯定有的小伙伴会说我知道还用问你呀,那是我们从头到尾就没有哪个地方写过登陆成功或失败的返回,好了废话不多说上代码:

   @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests() //授权配置(启用基于 HttpServletRequest 的访问限制,开始配置哪些URL需要被保护、哪些不需要被保护)
                .antMatchers("/admin/**").hasRole("admin") //配置/admin/**接口,拥有admin角色的可访问
                .antMatchers("/user/**").hasRole("user") //配置/user/**接口,拥有user角色的可访问
                .and().formLogin()
                .successHandler(new AuthenticationSuccessHandler() {
                    @Override
                    public void onAuthenticationSuccess(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Authentication authentication) throws IOException, ServletException {
                        httpServletResponse.setContentType("application/json;charset=utf-8");
                        PrintWriter out = httpServletResponse.getWriter();
                        out.write(new ObjectMapper().writeValueAsString("登陆成功!"));
                        out.flush();
                        out.close();
                    }
                })
                .failureHandler(new AuthenticationFailureHandler() {
                    @Override
                    public void onAuthenticationFailure(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AuthenticationException e) throws IOException, ServletException {
                        httpServletResponse.setContentType("application/json;charset=utf-8");
                        PrintWriter out = httpServletResponse.getWriter();
                        out.write(new ObjectMapper().writeValueAsString("登陆失败!"));
                        out.flush();
                        out.close();
                    }
                })
                .and().csrf().disable(); //禁用CSRF保护
    }

有人肯定又有话要说了 JDK1.8Lambda 表达式 用起来不香吗,还用这个,马上安排:

  @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests() //授权配置(启用基于 HttpServletRequest 的访问限制,开始配置哪些URL需要被保护、哪些不需要被保护)
                .antMatchers("/admin/**").hasRole("admin") //配置/admin/**接口,拥有admin角色的可访问
                .antMatchers("/user/**").hasRole("user") //配置/user/**接口,拥有user角色的可访问
                .and().formLogin()
                .successHandler((httpServletRequest, httpServletResponse, authentication) -> {
                    httpServletResponse.setContentType("application/json;charset=utf-8");
                    PrintWriter out = httpServletResponse.getWriter();
                    out.write(new ObjectMapper().writeValueAsString("登陆成功!"));
                    out.flush();
                    out.close();
                })
                .failureHandler((httpServletRequest, httpServletResponse, e) -> {
                    httpServletResponse.setContentType("application/json;charset=utf-8");
                    PrintWriter out = httpServletResponse.getWriter();
                    out.write(new ObjectMapper().writeValueAsString("登陆失败!"));
                    out.flush();
                    out.close();
                })
                .and().csrf().disable(); //禁用CSRF保护
    }

重启项目,登陆:
SpringBoot整合SpringSecurity学习笔记 SpringSecurity入门_第8张图片SpringBoot整合SpringSecurity学习笔记 SpringSecurity入门_第9张图片
那么登陆有了,注销怎么弄呢?直接上代码:

  @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests() //授权配置(启用基于 HttpServletRequest 的访问限制,开始配置哪些URL需要被保护、哪些不需要被保护)
                .antMatchers("/admin/**").hasRole("admin") //配置/admin/**接口,拥有admin角色的可访问
                .antMatchers("/user/**").hasRole("user") //配置/user/**接口,拥有user角色的可访问
                .and().formLogin()
                .successHandler((httpServletRequest, httpServletResponse, authentication) -> {
                    httpServletResponse.setContentType("application/json;charset=utf-8");
                    PrintWriter out = httpServletResponse.getWriter();
                    out.write(new ObjectMapper().writeValueAsString("登陆成功!"));
                    out.flush();
                    out.close();
                })
                .failureHandler((httpServletRequest, httpServletResponse, e) -> {
                    httpServletResponse.setContentType("application/json;charset=utf-8");
                    PrintWriter out = httpServletResponse.getWriter();
                    out.write(new ObjectMapper().writeValueAsString("登陆失败!"));
                    out.flush();
                    out.close();
                })
                .and().logout()
                .logoutSuccessHandler((httpServletRequest, httpServletResponse, e) -> {
                    httpServletResponse.setContentType("application/json;charset=utf-8");
                    PrintWriter out = httpServletResponse.getWriter();
                    out.write(new ObjectMapper().writeValueAsString("注销成功!"));
                    out.flush();
                    out.close();

                })
                .and().csrf().disable(); //禁用CSRF保护
    }

走起:
SpringBoot整合SpringSecurity学习笔记 SpringSecurity入门_第10张图片
好了,到这里我们SpringBoot整合SpringSecurity的入门级(基于内存用户名和密码的登陆,登出)操作就完成了

本博客是博主一字一字手敲出来的 , 如果大家觉得我哪里有不对的地方,欢迎大家在评论区给我指出来

你可能感兴趣的:(SpringSecurity)