SpringSecurity简介和基本使用

Spring Security 简介

Spring Security 是一个强大的可高度自定义的认证授权安全框架.可以跟Spring无缝结合.环境要求JDK8以上

Spring Security Hello World程序

  • 引pom文件
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>
    </dependencies>
  • 写一个TestController和主启动类
@RestController
public class TestController {

    @GetMapping("/test")
    public String test() {
        return "hello security!";
    }
}
@SpringBootApplication
public class SecurityMain {
    public static void main(String[] args) {
        SpringApplication.run(SecurityMain.class, args);
    }
}
  • Spring Security 启动默认自动生成了一个用户 用户名为user 密码为

    image-20210408102718489

  • 访问testController默认会进入Spring Security定义的登陆页面

    image-20210408102815666

  • 输入用户名 user 密码为控制台自动生成的密码即可访问成功

    image-20210408102903378

Spring Security 基本原理

  • Spring Security 本质上是一个过滤器链

  • Spring Security 底层核心的有10几个过滤器

    • FilterSecurityInterceptor 方法级别的过滤器是最底层的过滤器
    • ExceptionTranslationFilter 异常处理的过滤器链,用来处理认证授权中的各种异常 AuthenticationException AccessDeniedException
    • UsernamePasswordAuthenticationFilter 基于用户名密码的过滤器链 验证 /login的Post请求的用户验证
  • Spring Security 通过DelegatingFilterProxy来配置过滤器

    • doFilter方法中的 delegateToUse = initDelegate(wac); wac就是WebApplicationContext

      image-20210408114042567

    • initDelegate 本质上就是从Sping容器中拿一个FilterChainFactory的组件并执行的init方法

    image-20210408114138015

  • Security中核心两个接口UserDetailService PasswordEncoder

    • UserDetailService中定义如何获取通过用户名获取用户信息 比如从数据库中查询 返回UserDetails对象是Spring Scurity包下的

      public interface UserDetailsService {
      	UserDetails loadUserByUsername(String username) throws UsernameNotFoundException;
      }
      
    • PasswordEncoder定义密码的加密方式 默认建议使用BCryptPasswordEncoder

Spring Security 的三种设置用户名密码的方式

  • 配置文件

    image-20210408114858003

  • 通过配置类 继承 WebSecurityConfigurerAdapter 重写 protected void configure(AuthenticationManagerBuilder auth) throws Exception方法自定义用户授权的方式

    package com.corn.config;
    
    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.WebSecurityConfigurerAdapter;
    import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
    import org.springframework.security.crypto.password.PasswordEncoder;
    
    /**
     * @author : Jim Wu
     * @version 1.0
     * @function :
     * @since : 2021/4/8 11:49
     */
    
    @Configuration
    public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
    
    
        /**
         * 密码解密器
         * @return
         */
        @Bean
        public PasswordEncoder passwordEncoder(){
            return new BCryptPasswordEncoder();
        }
    
        /**
         * 配置一个内存的用户
         * @param auth
         * @throws Exception
         */
        @Override
        protected void configure(AuthenticationManagerBuilder auth) throws Exception {
            String password = passwordEncoder().encode("123");
            auth.inMemoryAuthentication().withUser("root").password(password).authorities("add","delete","select").roles("admin");
        }
    }
    
  • 自定义UserDetailService来实现自定义的用户账号密码查询逻辑 比如通过数据库

    • 添加mybatis plus相关依赖用于数据库操作

              <dependency>
                  <groupId>com.baomidou</groupId>
                  <artifactId>mybatis-plus-boot-starter</artifactId>
                  <version>3.4.2</version>
              </dependency>
      
              <dependency>
                  <groupId>mysql</groupId>
                  <artifactId>mysql-connector-java</artifactId>
              </dependency>
      
      
    • 创建数据库 管理用户

      CREATE TABLE `sys_user` (
        `id` int NOT NULL,
        `username` varchar(255) COLLATE utf8_bin DEFAULT NULL,
        `password` varchar(255) COLLATE utf8_bin DEFAULT NULL,
        PRIMARY KEY (`id`)
      ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
      
    • 添加数据库连接配置

      spring:
        datasource:
          driver-class-name: com.mysql.cj.jdbc.Driver
          username: root
          password: root
          url: jdbc:mysql://localhost:3306/tutorial?useUnicode=true&characterEncoding=UTF8&zeroDateTimeBehavior=convertToNull&serverTimezone=Asia%2FShanghai&allowMultiQueries=true
      
    • 创建实体和Mapper

      
      package com.corn.entity;
      
      import com.baomidou.mybatisplus.annotation.TableId;
      import com.baomidou.mybatisplus.annotation.TableName;
      import lombok.Data;
      @Data
      @TableName("sys_user")
      public class SysUser {
          @TableId
          private Long id;
      
          private String username;
      
          private String password;
      
      }
      
      package com.corn.mapper;
      
      import com.baomidou.mybatisplus.core.mapper.BaseMapper;
      import com.corn.entity.SysUser;
      
      public interface SysUserMapper extends BaseMapper<SysUser> {
      }
      
      
    • 添加@MapperScan注解

      @MapperScan(basePackages = {"com.corn.mapper"})
      @SpringBootApplication
      public class SecurityMain {
          public static void main(String[] args) {
              SpringApplication.run(SecurityMain.class, args);
          }
      }
      
    • 自定义UserDetailsService 实现查询数据库逻辑

      package com.corn.security;
      
      import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
      import com.corn.entity.SysUser;
      import com.corn.mapper.SysUserMapper;
      import lombok.RequiredArgsConstructor;
      import org.springframework.security.core.authority.AuthorityUtils;
      import org.springframework.security.core.userdetails.User;
      import org.springframework.security.core.userdetails.UserDetails;
      import org.springframework.security.core.userdetails.UserDetailsService;
      import org.springframework.security.core.userdetails.UsernameNotFoundException;
      import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
      import org.springframework.security.crypto.password.PasswordEncoder;
      import org.springframework.stereotype.Service;
      
      
      @RequiredArgsConstructor
      @Service
      public class MyUserDetailService implements UserDetailsService {
          private final SysUserMapper userMapper;
      
          @Override
          public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
              LambdaQueryWrapper<SysUser> wrapper = new LambdaQueryWrapper<>();
              wrapper.eq(SysUser::getUsername, username);
              SysUser sysUser = userMapper.selectOne(wrapper);
              if (null == sysUser)
                  throw new UsernameNotFoundException("用户不存在");
              PasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
              return new User(sysUser.getUsername(), passwordEncoder.encode(sysUser.getPassword()), AuthorityUtils.createAuthorityList("add", "delete", "select"));
          }
      }
      
      
    • 配置Security 配置添加UserDetailsService

          @Autowired
          private UserDetailsService userDetailsService;
      
          /**
           * 使用UserDetailService来查询用户信息
           *
           * @param auth
           * @throws Exception
           */
          @Override
          protected void configure(AuthenticationManagerBuilder auth) throws Exception {
              auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
          }
      
      

自定义登录页面 登录请求地址

  • 覆盖protected void configure(HttpSecurity http) throws Exception

        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http.csrf().disable() // 关闭csrf验证
                    .formLogin().loginPage("/html/login") // 自定义登录页面
                    .defaultSuccessUrl("/html/index") // 默认登录成功跳转
                    .loginProcessingUrl("/user/login") // 登录处理器controller POST请求地址
                    .permitAll() // 放行
                    .and()
                    .authorizeRequests()
                    .antMatchers("/", "/hello").permitAll() // / 和 /hello 放行 建议可以放在配置文件中
                    .anyRequest().authenticated(); // 其他所有请求必须认证
        }
    
  • 需要注意的是关闭csrf的验证

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值