SpringSecurity采坑与实战

简介

整合下springboot与security,通过二者简单的搭建一个登录访问的权限控制,话不多说直接上实战

HellWord

导入pom依赖

<!-- 添加springsecurity依赖 -->
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-config</artifactId>
        </dependency>

由于我之前添加了springboot的父类所以这里只需要直接导入组名和依赖名称就可以了

启动你的项目

这里写图片描述
你会发现项目的接口都添加了访问控制.看一下控制台

Using default security password: a800db21-c227-49a3-85f6-2b5434c67ab2

有这样的一行代码输出,说明了默认的用户名和密码

    User user = this.securityProperties.getUser();
            if (user.isDefaultPassword()) {
                logger.info(String.format("%n%nUsing default security password: %s%n",
                        user.getPassword()));
            }

通过这段代码可以看到在控制台输出了一个日志,密码是从user中取出来的,进入user中查看一下果然

        private String name = "user";
        private String password = UUID.randomUUID().toString();

默认用户名为user,密码是通过uuid自动生成的.

security:
  user:
    name: admin
    password: admin
    role: admin

用户名和密码可以再application中自定义,也可以在重写configure方法或者绑定数据库来定义

优化你的security

@EnableWebSecurity
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
   protected void configure(HttpSecurity http) throws Exception {
        http
                .csrf().disable()
                .authorizeRequests()
                .requestMatchers(CorsUtils::isPreFlightRequest).permitAll()
                .antMatchers("/resources/**", "/signup", "/about").permitAll()
                .antMatchers("/admin/**").hasRole("admin")
                .antMatchers("/db/**").access("hasRole('admin') and hasRole('dba')")
                .and()
                .formLogin()
                .loginPage("/security/toLogin")
                .loginProcessingUrl("/security/login")
                .successForwardUrl("/security/success/login")
                .failureForwardUrl("/security/false")
                .and()
                .logout()
                .logoutUrl("/security/logout")
                .logoutSuccessUrl("/security/success/logout")
                .and()
                .exceptionHandling().accessDeniedPage("/security/denied")
                .and()
                .rememberMe()
                .key("jbzm-Security")
                .rememberMeCookieName("cookieName")
                .rememberMeParameter("paramName")
                .tokenRepository(new InMemoryTokenRepositoryImpl());
    }
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication()
                .withUser("admin").password("admin").roles("admin")
                .and()
                .withUser("dba").password("dba").roles("dba", "admin");
    }
}

下面开始分析这段代码

添加@EnableWebSecurity

@Retention(value = java.lang.annotation.RetentionPolicy.RUNTIME)
@Target(value = { java.lang.annotation.ElementType.TYPE })
@Documented
@Import({ WebSecurityConfiguration.class,
        SpringWebMvcImportSelector.class })
@EnableGlobalAuthentication
@Configuration
  • 这是@EnableWebSecurity的注解构成,比较明显,自动导入bean,以及可以当做配置文件

继承WebSecurityConfigurerAdapter

  • 通过继承该方法来添加security的控制
    • 这里需要重写他的三个方法
http
    .authorizeRequests()
        .anyRequest().authenticated()
        .and()
    .formLogin().and()
    .httpBasic();
  • 这是在默认情况下security默认加载的,其中formLogin就是默认添加的登录验证模块

一个坑csrf

  • CSRF(Cross-site request forgery跨站请求伪造,也被称为“One Click Attack” 或者Session Riding,攻击方通过伪造用户请求访问受信任站点。
http
    .csrf().and()    <- 这里添加了csrf验证
    .addFilter(new WebAsyncManagerIntegrationFilter())
    .exceptionHandling().and()
    .headers().and()
  • 简而言之就是跨域访问的问题,security4.0之后会默认开启csrf安全验证,需要我们手动去关闭.

添加访问权限

.requestMatchers(CorsUtils::isPreFlightRequest).permitAll()
                .antMatchers("/resources/**", "/signup", "/about").permitAll()
                .antMatchers("/admin/**").hasRole("admin")
                .antMatchers("/db/**").access("hasRole('admin') and hasRole('dba')")
  • 添加cors跨域验证,以及对应权限允许开放的访问地址

这是测试代码

@RestController
public class TestLoginController {
    @GetMapping("lol")
    public Object testLol() {
        return "成功/lol";
    }

    @GetMapping("resources/lol")
    public Object testResources() {
        return "成功/resources";
    }

    @GetMapping("admin/lol")
    public Object testAdmin() {
        return "成功/admin";
    }

    @GetMapping("db/lol")
    public Object testDba() {
        return "成功/db";
    }
}

设置登录/登出跳转

                 .formLogin()
                 .loginPage("/security/toLogin")
                 .loginProcessingUrl("/security/login")
                 .successForwardUrl("/security/success/login")
                 .failureForwardUrl("/security/false")
                 .and()
                 .logout()
                 .logoutUrl("/security/logout")
                 .logoutSuccessUrl("/security/success/logout")
  • logPage是登录页面
    • 由于前后台分离,通过返回json来告知前台跳转登录页
  • loginProcessingUrl
    • 填写验证登录的请求地址
  • successForwardUrl
    • 填写成功后跳转的地址,同样通过json告知前台登录成功
  • failureForwardUrl
    • 登录失败调调专路径,同上使用json

登出功能同理,不做解释了,下面是测试用的接口,测试登录

@RestController
public class Test {
    @GetMapping("lol")
    public Object testLol() {
        return "成功";
    }

    @GetMapping("resources/lol")
    public Object testResources() {
        return "成功";
    }

    @GetMapping("admin/lol")
    public Object testAdmin() {
        return "成功";
    }

    @GetMapping("db/lol")
    public Object testDba() {
        return "成功";
    }
}

添加权限不足跳转,以及cookie保存

             .exceptionHandling().accessDeniedPage("/security/denied")
             .and()
             .rememberMe()
             .key("jbzm-Security")
             .rememberMeCookieName("cookieName")
             .rememberMeParameter("paramName")
             .tokenRepository(new InMemoryTokenRepositoryImpl());
  • 这里不做过多介绍了,很好理解

猜你喜欢

转载自blog.csdn.net/qq_19663899/article/details/79478922
今日推荐