springsecurity通俗易懂

本文详细介绍了如何使用Spring Security保护Spring Boot应用中的接口,包括用户注册、登录验证及自定义权限配置的过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

注:本篇写作思维旨在引导初学security的码友,一步步的达到可以灵活使用的地步,建议各位读者阅读前,先把我的源代码下载下来,对着master分支看比较好理解,磨刀不误砍柴工,https://github.com/1074952839/spring-security-demo01.git

springsecurity的引入(springboot版本为:2.1.3)

我们先准备一下如下的代码:

  1. 新建springboot项目,命名为:springboot-security-oauth2(之所以这么命名,是为了后期扩展项目达到企业级开发的目的)

  2. 然后我们建一个controller包,并在其中建一个UserController,内容如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    /**
    * Created by xk on 2018/11/26
    */
    @RestController
    @RequestMapping("/user")
    public class UserController {
    @GetMapping
    public String get(){
    return "看到我了吗?";
    }
    }
  3. 然后我们启动服务,访问localhost:8080/user,看到如下效果:

    image-20190228165043925

  4. 那问题来了,我想让这个接口受到保护,也就是需要用户登录后,才能访问这个接口怎么办呢?那好办呀,我们引入springsecurity试试呀!继续往下看吧。

我们继续接着上面的例子往下走,我们在pom.xml里面加入如下2个依赖:

1
2
3
4
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>

然后我们再重新启动项目,访问localhost:8090/user,看到如下效果:

image-20190228225525071

哎呀,居然直接跳到localhost:8090/login地址了,然后出现这个表单了,这是因为springsecurity的默认配置。

那我们怎么才能访问到localhost:8090/user接口呢?

直捣黄龙吧,security默认的用户名为:user,密码可以在项目启动时发现,如图:

image-20190228230017073

填写完成后,就可以访问到localhost:8090/user接口了。

那么问题来了,我想自己做个注册功能,然后用我自己注册的用户名和密码登录咋办呢?

  1. 我们在MySQL的security-demo库里建一个user表,表结构如下:

    image-20190301084751810

  2. UserController里新增insert方法:

    1
    2
    3
    4
    5
    6
    7
    @Autowired
    private UserRepository userRepository; //本文档使用的是spring-data-jpa做数据访问框架

    @GetMapping("/register")//这么写其实不符合restful规范,这里为了好写demo,暂且这么写。
    public ResponseEntity<ResponseData> insert(User user){
    return ResponseEntity.ok(new ResponseData(userRepository.save(user)));//ResponseData这个类是我自己写的类
    }
  1. 重新启动项目,我们发送localhost:8090/user/register?name=test&password=test请求来注册一个用户,我们发现这时,请求并没有到UserController里,而是直接给我们返回一个登陆页面了!!!

  2. 上面的问题,其实不难发现,因为我们引入了spring-security,我们前面已经说了,他会默认的对所有请求做拦截,需要登录才能请求相关接口,而实际情况下,我们不应该拦截用户注册的请求呀?所以继续看如下神操作:

    1. 我们新建一个config包,然后新建WebSecurityConfig类,内容如下:

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      /**
      * Created by xk on 2018/11/26
      */
      @Component
      public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
      @Override
      protected void configure(HttpSecurity http) throws Exception {
      http.formLogin()
      .and()
      .authorizeRequests()
      .antMatchers("/user/register").permitAll()//这里我们允许/user/register请求可以直接访问,其它请求都需要认证。
      .anyRequest()
      .authenticated();
      }
    2. 然后我们继续发送localhost:8090/user/register?name=test&password=test请求来注册一个用户,可以发现浏览器给我们返回了用户的信息,并且数据库已经有记录了。

      image-20190301102411207

    3. 接下来,我们继续访问localhost:8090/user吧,结果又跳到了登陆页面,那我们拿test,test登陆试试,结果悲剧了。。。。。。。。

      image-20190301102900769

      咋还登陆不上去呢???

    4. 接下来,继续神操作,我们再config包里新建UserService类,内容如下:

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      @Component
      public class UserService implements UserDetailsService {
      @Autowired
      private UserRepository userRepository;
      @Override
      public UserDetails loadUserByUsername(String name) throws UsernameNotFoundException {
      top.xiekun.springbootsecurityoauth2.domain.User user = userRepository.findByName(name);
      if (user != null){
      return new User(user.getName(), user.getPassword(), AuthorityUtils.commaSeparatedStringToAuthorityList("admin"));//这段话,后面的分享会讲解的。
      }
      return null;
      }
      }
    5. 我们继续访问localhost:8090/user吧,结果又跳到了登陆页面,那我们拿test,test登陆试试,结果又悲剧了,还是登陆不上去呀!我们先看一下下图:

      image-20190301130503173

      image-20190301130714438

      image-20190301130606248

      其实通过调试我们发现,springsecurity在做密码比对时,会先查看这个项目有木有配置PasswordEncoder,若没有的话就会抛出一个上图所示异常,所以才登陆不成功。

    6. 了解了问题的原因,那接下来我们将代码进行如下修改:

      1. WebSecurityConfig类添加如下内容:

        1
        2
        3
        4
        @Bean
        private PasswordEncoder passwordEncoder(){
        return new BCryptPasswordEncoder();
        }
      2. UserController类修改为如下内容:

        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
        17
        18
        19
        20
        21
        22
        23
        /**
        * Created by xk on 2018/11/26
        */
        @RestController
        @RequestMapping("/user")
        public class UserController {
        @Autowired
        private UserRepository userRepository;

        @Autowired
        private PasswordEncoder passwordEncoder;

        @GetMapping
        public List<User> get(){
        return userRepository.findAll();
        }

        @GetMapping("/register")
        public ResponseEntity<ResponseData> insert(User user){
        user.setPassword(passwordEncoder.encode(user.getPassword()));
        return ResponseEntity.ok(new ResponseData(userRepository.save(user)));
        }
        }
      3. 接下来我们发送localhost:8090/user/register?name=xiekun&password=123重新注册个用户,可以看到数据库多了一条记录,我们用新注册的用户名,密码发现登陆可以成功了。此时访问localhost:8090/user,发现可以成功查询到所有的用户了。

        image-20190301132309392

至此,我们已经完成了从用户注册到登陆成功后可以访问其他接口的目的了。(实际项目中,我们不可能说只要用户登录了,就可以请求各种接口了,我们应该给每个用户设置角色和权限,每个接口上面也应该注明需要用户有哪种角色和权限才能请求这个接口,那么接下来我会继续更新security+oauth2在项目中如何使用的。)

<think>好的,用户让我介绍一下Spring Security解析,我需要先理清思路,确保回答结构清晰。首先,我应该从基础开始,解释Spring Security是什么,它的核心功能和作用。然后,逐步深入到架构和关键组件,比如过滤器链、SecurityContext、认证和授权机制。可能还需要提到一些高级特性,比如方法级安全、OAuth2集成,以及常见的安全防护措施,比如CSRF和CORS支持。 接下来,用户可能想知道如何实际使用Spring Security,所以需要简要说明配置步骤,包括依赖添加、配置类编写以及自定义用户认证的方法。还要注意用户可能的疑问点,比如如何扩展功能或处理常见问题,例如自定义登录页面或权限管理。 需要确保使用中文,并且遵循系统级指令中的格式要求,数学表达式和公式使用正确的LaTeX格式。不过在这个问题中可能用不到数学公式,但如果有涉及技术术语或代码,可能需要适当处理。比如在提到版本号或代码示例时,使用正确的代码块格式,但根据用户要求,这里可能不需要,只需用文字描述。 另外,用户可能对Spring Security的内部工作原理感兴趣,比如过滤器链如何工作,认证流程是怎样的,所以需要详细说明这些部分的结构和流程。同时,要注意避免过于技术化的术语,用通俗易懂的语言解释,确保用户能够逐步理解。 最后,总结部分要强调Spring Security的优势和适用场景,帮助用户形成整体认识。检查是否有遗漏的重要点,比如安全防护措施中的CSRF和CORS,或者与其他技术的整合,如OAuth2。确保回答结构合理,层次分明,符合用户要求的“结构清晰,逐步解决问题”的需求。</think>Spring Security 是 Java 生态中广泛使用的安全框架,专注于为 Spring 应用提供身份认证(Authentication)、授权(Authorization)和攻击防护能力。以下是其核心解析: --- ### 一、核心功能分层 1. **身份认证** - 支持多种认证方式:表单登录、HTTP Basic、OAuth2、LDAP、JWT 等 - 核心接口 `UserDetailsService`:通过 `loadUserByUsername` 加载用户信息 - 密码编码器 `PasswordEncoder`:强制使用加密存储(如 BCrypt) 2. **访问控制** - 基于角色(Role)或权限(Authority)的细粒度控制 - 支持表达式语言(SpEL)配置复杂规则 示例:`hasRole('ADMIN') && hasIpAddress('192.168.1.0/24')` 3. **安全防护** - CSRF 防护(默认开启) - CORS 配置 - Session 固定攻击防护 - 安全头部注入(X-Content-Type-Options 等) --- ### 二、架构解析 #### 1. 过滤器链机制 Spring Security 通过 `FilterChainProxy` 管理过滤器链: $$ \text{HTTP请求} \rightarrow \begin{cases} \text{SecurityContextPersistenceFilter} \\ \text{UsernamePasswordAuthenticationFilter} \\ \text{FilterSecurityInterceptor} \\ \vdots \\ \text{自定义过滤器} \end{cases} $$ 每个过滤器处理特定安全任务,按顺序执行。 #### 2. 认证流程 ```plaintext 1. 用户提交凭证 → 2. AuthenticationManager 调度认证 → 3. Provider 调用 UserDetailsService 验证 → 4. 生成 Authentication 对象 → 5. 存储到 SecurityContextHolder ``` #### 3. 授权决策 - `AccessDecisionManager` 通过投票机制决定访问权限 - 典型实现:`AffirmativeBased`(一票通过即授权) --- ### 三、关键配置示例 ```java @Configuration @EnableWebSecurity public class SecurityConfig { @Bean public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { http .authorizeHttpRequests(auth -> auth .requestMatchers("/admin/**").hasRole("ADMIN") .anyRequest().authenticated() ) .formLogin(form -> form .loginPage("/login") .permitAll() ) .logout(logout -> logout .logoutSuccessUrl("/") ); return http.build(); } @Bean public UserDetailsService users() { UserDetails user = User.builder() .username("user") .password("{bcrypt}$2a$10$...") .roles("USER") .build(); return new InMemoryUserDetailsManager(user); } } ``` --- ### 四、高级特性 1. **方法级安全** - 通过 `@PreAuthorize` 注解实现方法调用前鉴权 ```java @PreAuthorize("hasAuthority('WRITE_POST')") public void createPost(Post post) { ... } ``` 2. **OAuth2 集成** - 支持资源服务器和客户端配置 - 与 JWT 无缝整合 3. **响应式安全** - 为 WebFlux 应用提供响应式安全支持 --- ### 五、最佳实践 1. **自定义认证逻辑** - 实现 `UserDetailsService` 对接数据库 - 自定义 `AuthenticationProvider` 处理特殊认证流程 2. **权限动态加载** - 通过 `FilterInvocationSecurityMetadataSource` 实现动态 URL 权限控制 3. **监控与审计** - 使用 `ApplicationEventPublisher` 跟踪安全事件 - 集成 Spring Actuator 暴露健康检查端点 Spring Security 通过模块化设计和高度可扩展性,能够满足从单体应用到微服务架构的安全需求,是构建企业级安全体系的基石工具。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值