SpringSecurity 安全框架详解

这篇具有很好参考价值的文章主要介绍了SpringSecurity 安全框架详解。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

SpringSecurity 安全框架详解

1.简介

先赘述一下身份认证和用户授权:

  • 用户认证(Authentication):系统通过校验用户提供的用户名和密码来验证该用户是否为系统中的合法主体,即是否可以访问该系统;
  • 用户授权(Authorization):系统为用户分配不同的角色,以获取对应的权限,即验证该用户是否有权限执行该操作;

Web应用的安全性包括用户认证和用户授权两个部分,而Spring Security(以下简称Security)基于Spring框架,正好可以完整解决该问题。

它的真正强大之处在于它可以轻松扩展以满足自定义要求。

2.原理

Security可以看做是由一组filter过滤器链组成的权限认证。它的整个工作流程如下所示:
安全框架全局,Springboot专栏,安全,mybatis,spring boot,spring,spring security
图中绿色认证方式是可以配置的,橘黄色和蓝色的位置不可更改:

  • FilterSecurityInterceptor:最后的过滤器,它会决定当前的请求可不可以访问Controller
  • ExceptionTranslationFilter:异常过滤器,接收到异常消息时会引导用户进行认证;

2.1 项目准备

我们使用Spring Boot框架来集成。

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter</artifactId>
</dependency>

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    <exclusions>
        <exclusion>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-tomcat</artifactId>
        </exclusion>
    </exclusions>
</dependency>

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-undertow</artifactId>
</dependency>

<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
</dependency>

<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-boot-starter</artifactId>
    <version>3.4.0</version>
</dependency>

<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
</dependency>

<!-- 阿里JSON解析器 -->
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>1.2.74</version>
</dependency>

<dependency>
    <groupId>joda-time</groupId>
    <artifactId>joda-time</artifactId>
    <version>2.10.6</version>
</dependency>

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
</dependency>

application.yml配置

spring:
 application:
  name: securityjwt
 datasource:
  driver-class-name: com.mysql.cj.jdbc.Driver
  url: jdbc:mysql://127.0.0.1:3306/cheetah?characterEncoding=utf-8&useSSL=false&serverTimezone=UTC
  username: root
  password: 123456

server:
 port: 8080

mybatis:
 mapper-locations: classpath:mapper/*.xml
 type-aliases-package: com.itcheetah.securityjwt.entity
 configuration:
  map-underscore-to-camel-case: true

rsa:
 key:
  pubKeyFile: C:\Users\Desktop\jwt\id_key_rsa.pub
  priKeyFile: C:\Users\Desktop\jwt\id_key_rsa

3.SQL文件

/**
\* sys_user_info
**/*

SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;

*-- ----------------------------*
*-- Table structure for sys_user_info*
*-- ----------------------------*
DROP TABLE IF EXISTS `sys_user_info`;
CREATE TABLE `sys_user_info` (
 `id` bigint(20) NOT NULL AUTO_INCREMENT,
 `username` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
 `password` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
 PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 3 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;

SET FOREIGN_KEY_CHECKS = 1;


*/**
\* product_info
**/*

SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;

*-- ----------------------------*
*-- Table structure for product_info*
*-- ----------------------------*
DROP TABLE IF EXISTS `product_info`;
CREATE TABLE `product_info` (
 `id` bigint(20) NOT NULL AUTO_INCREMENT,
 `name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
 `price` decimal(10, 4) NULL DEFAULT NULL,
 `create_date` datetime(0) NULL DEFAULT NULL,
 `update_date` datetime(0) NULL DEFAULT NULL,
 PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 4 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;

SET FOREIGN_KEY_CHECKS = 1;

2.2 jwt 引入依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>

<!--Token生成与解析-->
<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt</artifactId>
    <version>0.9.1</version>
</dependency>

引入之后启动项目,会有如图所示:

安全框架全局,Springboot专栏,安全,mybatis,spring boot,spring,spring security

其中用户名为user,密码为上图中的字符串。

2.3 有关Security类详解

2.3.1 SecurityConfig详解
//开启全局方法安全性*
@EnableGlobalMethodSecurity(prePostEnabled=true, securedEnabled=true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {

  *//认证失败处理类*
  @Autowired
  private AuthenticationEntryPointImpl unauthorizedHandler;

  *//提供公钥私钥的配置类*
  @Autowired
  private RsaKeyProperties prop;

  @Autowired
  private UserInfoService userInfoService;
  
  @Override
  protected void configure(HttpSecurity httpSecurity) throws Exception {
    httpSecurity
        *// CSRF禁用,因为不使用session*
        .csrf().disable()
        *// 认证失败处理类*
        .exceptionHandling().authenticationEntryPoint(unauthorizedHandler).and()
        *// 基于token,所以不需要session*
        .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
        *// 过滤请求*
        .authorizeRequests()
        .antMatchers(
            HttpMethod.GET,
            "/*.html",
            "/**/*.html",
            "/**/*.css",
            "/**/*.js"
        ).permitAll()
        *// 除上面外的所有请求全部需要鉴权认证*
        .anyRequest().authenticated()
        .and()
        .headers().frameOptions().disable();
    *// 添加JWT filter*
    httpSecurity.addFilter(new TokenLoginFilter(super.authenticationManager(), prop))
        .addFilter(new TokenVerifyFilter(super.authenticationManager(), prop));
  }

  *//指定认证对象的来源*
  public void configure(AuthenticationManagerBuilder auth) throws Exception {
    
    auth.userDetailsService(userInfoService)
    *//从前端传递过来的密码就会被加密,所以从数据库*
    *//查询到的密码必须是经过加密的,而这个过程都是*
    *//在用户注册的时候进行加密的。*
    .passwordEncoder(passwordEncoder());
  }

  *//密码加密*
  @Bean
  public BCryptPasswordEncoder passwordEncoder(){
    return new BCryptPasswordEncoder();
  }
}

「拦截规则」

  • anyRequest:匹配所有请求路径
  • accessSpringEl表达式结果为true时可以访问
  • anonymous:匿名可以访问
  • denyAll:用户不能访问
  • fullyAuthenticated:用户完全认证可以访问(非remember-me下自动登录)
  • hasAnyAuthority:如果有参数,参数表示权限,则其中任何一个权限可以访问
  • hasAnyRole:如果有参数,参数表示角色,则其中任何一个角色可以访问
  • hasAuthority:如果有参数,参数表示权限,则其权限可以访问
  • hasIpAddress:如果有参数,参数表示IP地址,如果用户IP和参数匹配,则可以访问
  • hasRole:如果有参数,参数表示角色,则其角色可以访问
  • permitAll:用户可以任意访问
  • rememberMe:允许通过remember-me登录的用户访问
  • authenticated:用户登录后可访问
2.3.2 认证失败处理类
/**
 \* 返回未授权
 \*/*
@Component
public class AuthenticationEntryPointImpl implements AuthenticationEntryPoint, Serializable {

  private static final long serialVersionUID = -8970718410437077606L;

  @Override
  public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException e)
      throws IOException {
    int code = HttpStatus.UNAUTHORIZED;
    String msg = "认证失败,无法访问系统资源,请先登陆";
    ServletUtils.renderString(response, JSON.toJSONString(AjaxResult.error(code, msg)));
  }
}

2.4 认证流程

2.4.1 自定义认证过滤器
public class TokenLoginFilter extends UsernamePasswordAuthenticationFilter {

  private AuthenticationManager authenticationManager;

  private RsaKeyProperties prop;

  public TokenLoginFilter(AuthenticationManager authenticationManager, RsaKeyProperties prop) {
    this.authenticationManager = authenticationManager;
    this.prop = prop;
  }

  */**
   \* @author cheetah
   \* @description 登陆验证
   \* @date 2021/6/28 16:17
   \* @Param [request, response]
   \* @return org.springframework.security.core.Authentication
   **/*
  public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
    try {
      UserPojo sysUser = new ObjectMapper().readValue(request.getInputStream(), UserPojo.class);
      UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(sysUser.getUsername(), sysUser.getPassword());
      return authenticationManager.authenticate(authRequest);
    }catch (Exception e){
      try {
        response.setContentType("application/json;charset=utf-8");
        response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
        PrintWriter out = response.getWriter();
        Map resultMap = new HashMap();
        resultMap.put("code", HttpServletResponse.SC_UNAUTHORIZED);
        resultMap.put("msg", "用户名或密码错误!");
        out.write(new ObjectMapper().writeValueAsString(resultMap));
        out.flush();
        out.close();
      }catch (Exception outEx){
        outEx.printStackTrace();
      }
      throw new RuntimeException(e);
    }
  }



  */**
   \* @author cheetah
   \* @description 登陆成功回调
   \* @date 2021/6/28 16:17
   \* @Param [request, response, chain, authResult]
   \* @return void
   **/*
  public void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authResult) throws IOException, ServletException {
    UserPojo user = new UserPojo();
    user.setUsername(authResult.getName());
    user.setRoles((List<RolePojo>)authResult.getAuthorities());
    *//通过私钥进行加密:token有效期一天*
    String token = JwtUtils.generateTokenExpireInMinutes(user, prop.getPrivateKey(), 24 * 60);
    response.addHeader("Authorization", "Bearer "+token);
    try {
      response.setContentType("application/json;charset=utf-8");
      response.setStatus(HttpServletResponse.SC_OK);
      PrintWriter out = response.getWriter();
      Map resultMap = new HashMap();
      resultMap.put("code", HttpServletResponse.SC_OK);
      resultMap.put("msg", "认证通过!");
      resultMap.put("token", token);
      out.write(new ObjectMapper().writeValueAsString(resultMap));
      out.flush();
      out.close();
    }catch (Exception outEx){
      outEx.printStackTrace();
    }
  }
}
2.4.2 登录流程

Security默认登录路径为/login,当我们调用该接口时,会在登录的时候调方法loadUserByUsername(username)

安全框架全局,Springboot专栏,安全,mybatis,spring boot,spring,spring security

安全框架全局,Springboot专栏,安全,mybatis,spring boot,spring,spring security

该方法的具体实现类

安全框架全局,Springboot专栏,安全,mybatis,spring boot,spring,spring security

如果用户名称不存在就直接抛出用户名或密码错误,如果用户名字存在,在把该用户对应的信息和权限用AdminUserDetails这个类接收

需要注意的是,这个接收用户信息的接受类需要实现SpringSecurity中的接口UserDetails

安全框架全局,Springboot专栏,安全,mybatis,spring boot,spring,spring security

如果密码正确的话,就把对应的用户用户信息和用户权限用UsernamePasswordAuthenticationToken初始化,并且增加Security框架中的过滤器增加该权限setAuthentication。

ps:这个类UsernamePasswordAuthenticationToken在下文验证token时会出现。

安全框架全局,Springboot专栏,安全,mybatis,spring boot,spring,spring security

如果Secruity框架都没啥问题了,这时候就掉用生成token的接口了

安全框架全局,Springboot专栏,安全,mybatis,spring boot,spring,spring security

token = jwtTokenUtil.generateToken(userDetails);

接口大概的实现方法,就是拿用户名称是做Jwt的载体

安全框架全局,Springboot专栏,安全,mybatis,spring boot,spring,spring security

2.4.3 这里顺便提一下Jwt

jwt简称json web token,他是由`.分割的三部分组成,这三部分依次是:

  • 头部(Header)
  • 负载(Payload)
  • 签名(Signature)

Header

JWT的Header中存储了所使用的加密算法和Token类型

{
   "alg" : "HS256",
   "typ" : "JWT"
}

Payload

payload表示负载,也是一个JSON对象,JWT规定了7个官方字段供选用。

iss (issuer) : 签发人
exp (expiration time) : 过期时间
sub (subject) : 主题
aud (audience) : 受众
nbf (Not Before) : 生效时间
iat (Issued At) : 签发时间
jti (JWT ID) : 编号

Signature

Signature部分是对前两部分的签名,防止数据篡改。
首先,需要指定一一个密钥(secret) 。 这个密钥只有服务器才知道,不能泄露给用户。然后,使用Header里面指定的签名算法(默认是HMAC SHA256),按照下面的公式产生签名。

JWT优缺点:

JWT拥有基于Token的会话管理方式所拥有的一切优势,不依赖Cookie,使得其可以防止CSRF攻击,也能在禁用Cookie的浏览器环境中正常运行。
而JWT的最大优势是服务端不再需要存储Session,使得服务端认证鉴权业务可以方便扩展,避免存储Session所需要引入的Redis等组件,降低了系统架构复杂度。但这也是JWT最大的劣势,由于有效期存储在Token中,JWT Token-旦签发,就会在有效期内-直可用,无法在服务端废止,当用户进行登出操作,只能依赖客户端删除掉本地存储的JWT Token,如果需要禁用用户,单纯使用JWT就无法做到了。

2.5 整体流程

安全框架全局,Springboot专栏,安全,mybatis,spring boot,spring,spring security
具体代码地址
https://github.com/hongjiatao/spring-boot-anyDemo
可以的话点赞三连,也是对我最大的支持。谢谢文章来源地址https://www.toymoban.com/news/detail-785592.html

到了这里,关于SpringSecurity 安全框架详解的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 038-安全开发-JavaEE应用&SpringBoot框架&MyBatis注入&Thymeleaf模版

    1、JavaEE-SpringBoot-WebAPP路由 2、JavaEE-SpringBoot-Mybatis注入 3、JavaEE-SpringBoot-ThymeleafSSTI 演示案例: ➢SpringBoot-Web应用-路由响应 ➢SpringBoot-数据库应用-Mybatis ➢SpringBoot-模版引擎-Thymeleaf Spring Boot是由Pivotal团队提供的一套 开源框架 ,可以简化spring应用的创建及部署。它提供了丰富的

    2024年03月09日
    浏览(37)
  • SpringSecurity安全框架简介

    Spring Security是Spring全家桶的成员,官方对它的介绍是: 从介绍里可以看出,Spring Security是一个可定制扩展的框架,它主要提供了身份验证和访问控制功能。而这两个功能也是基于框架的扩展机制开发的,下面让我们一起了解一下Spring Security的基本概念和扩展机制的实现原理。

    2024年02月08日
    浏览(42)
  • SpringSecurity安全框架

    我们使用这个springSecurity安全框架,作用是认证,授权,将 用户的权限和对应的资源进行绑定 , 默认的是在内存中保存的,实际开发中,是需要根据项目业务的需求 对某些方法进行重写, 使数据库中权限对应的资源进行绑定, 就是查看当前登录的用户所扮演的角色,该角色有哪些权限

    2024年02月22日
    浏览(35)
  • SpringSecurity安全框架 ——认证与授权

    目录  一、简介 1.1 什么是Spring Security 1.2 工作原理 1.3 为什么选择Spring Security 1.4 HttpSecurity 介绍🌟 二、用户认证 2.1 导入依赖与配置 2.2 用户对象UserDetails 2.3 业务对象UserDetailsService 2.4 SecurityConfig配置 2.4.1 BCryptPasswordEncoder密码编码器 2.4.2 RememberMe 记住登录信息 2.4.3 CSR

    2024年02月04日
    浏览(44)
  • SpringSecurity分布式安全框架

    Spring Security是一个基于Spring框架的安全框架,它提供了全面的安全解决方案,包括用户认证和用户授权等Web应用安全性问题。Spring Security可以轻松扩展以满足自定义需求,它的真正强大之处在于它可以轻松扩展以满足自定义要求。 对于分布式系统来说,Spring Security可以结合

    2024年02月08日
    浏览(49)
  • SpringSecurity框架快速搭建(SpringBoot整合Security)

    目录 Common类 Config类 CorsConfig(解决跨域问题) RedisConfig (Redis数据库配置) Spring Security (配置安全功能的类) expression类(Expression 类通常用于权限控制和安全策略的定义) SGExpressionRoot(判断用户是否具有某个权限) Filter类 JwtAuthenticationTokenFilter(解析token看是否放行) Handler类

    2024年02月09日
    浏览(44)
  • SpringSecurity安全框架学习——@PreAuthorize的实现原理

    首先我们打开@PreAuthorize注解的源码,然后按住Ctrl并单击PreAuthorize,可以看到在EnableMethodSecurity注解中有引用 (本文使用IDEA,后续不再复述) 查看EnableMethodSecurity源码,可以到,其引用了MethodSecuritySelector 按照惯例,打开MethodSecuritySelector 可以看到,当prePostEnabled=true时,会注

    2023年04月16日
    浏览(39)
  • 【花艺电商】SpringBoot集成MyBatis-Plus、Swagger2、SpringSecurity、OAuth2等技术整合开发

    目录 一、功能介绍 1. 说明 2. 功能实现 3. 技术应用 二、技术详述 1.MyBatis-Plus 主要体现 项目应用 2.SpringSecurity 应用作用 三、页面展示 1. 登入 2. 主页 3. 详情 4. 购物车 5. 订单 6. 沙箱支付 每篇一获 这个项目主要使用了 Spring Security 、 MyBatis-Plus 、 Redis 、 雪花ID 、 参数校验技

    2024年01月25日
    浏览(52)
  • Mybatis3详解 之 全局配置文件详解

    前面我们看到的Mybatis全局文件并没有全部列举出来,所以这一章我们来详细的介绍一遍,Mybatis的全局配置文件并不是很复杂,它的所有元素和代码如下所示: 注意:Mybatis的配置文件的顺序是严格按照从上至下的顺序声明,不颠倒顺序,如果颠倒了它们的顺序,那么Mybatis在

    2024年02月07日
    浏览(44)
  • SpringSecurity的安全认证的详解说明(附完整代码)

    SpringSecurity 登录认证和请求过滤器以及安全配置详解说明 系统环境:win10 Maven环境:apache-maven-3.8.6 JDK版本:1.8 SpringBoot版本:2.7.8 根据用户名和密码登录,登录成功后返回 Token 数据,将 token放到请求头中 ,每次请求后台携带 token 数据 携带token请求后台 ,后台认证成功,过滤

    2024年02月08日
    浏览(36)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包