用starter实现Oauth2中资源服务的统一配置

news2024/10/7 2:29:27

一、前言

Oauth2中的资源服务Resource需要验证令牌,就要配置令牌的解码器JwtDecoder,认证服务器的公钥等等。如果有多个资源服务Resource,就要重复配置,比较繁锁。把公共的配置信息抽取出来,制成starter,可以极大地简化操作。

  • 未使用starter的原来配置

在这里插入图片描述

在这里插入图片描述

二、制作starter

详细步骤参考:自定义启动器 Starter【保姆级教程】

1、完整结构图

在这里插入图片描述

2、外部引用模块

  • 名称:tuwer-oauth2-config-spring-boot-starter

  • 普通的 maven 项目

  • 资源服务中引入该模块的依赖即可

  • 模块中只有一个pom.xml文件,其余的都可删除

  • pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.tuwer</groupId>
    <artifactId>tuwer-oauth2-config-spring-boot-starter</artifactId>
    <version>1.0-SNAPSHOT</version>
    <description>oauth2-config启动器</description>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
        <!-- 编译编码 -->
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <dependencies>
        <!-- 自动配置模块 -->
        <dependency>
            <groupId>com.tuwer</groupId>
            <artifactId>tuwer-oauth2-config-spring-boot-starter-autoconfigure</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
    </dependencies>
</project>

3、自动配置模块

  • 核心模块

  • 名称:tuwer-oauth2-config-spring-boot-starter-autoconfigure

  • spring boot 项目

  • pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.6.7</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.tuwer</groupId>
    <artifactId>tuwer-oauth2-config-spring-boot-starter-autoconfigure</artifactId>
    <version>1.0-SNAPSHOT</version>
    <description>oauth2-config启动器自动配置模块</description>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
        <!-- 编译编码 -->
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <dependencies>
        <!-- 基础启动器 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <!-- 资源服务器 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-oauth2-resource-server</artifactId>
        </dependency>
        <!-- web -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!-- lombok -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.22</version>
        </dependency>
    </dependencies>
</project>
  • handler(拒绝访问、认证失败)处理类
package com.tuwer.config.handler;

import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.SneakyThrows;
import org.springframework.http.MediaType;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.web.access.AccessDeniedHandler;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashMap;

/**
 * <p>拒绝访问处理器</p>
 *
 * @author 土味儿
 * Date 2022/5/11
 * @version 1.0
 */
public class SimpleAccessDeniedHandler implements AccessDeniedHandler {
    @SneakyThrows
    @Override
    public void handle(HttpServletRequest request,
                       HttpServletResponse response,
                       AccessDeniedException accessDeniedException
    ) throws IOException, ServletException {
        //todo your business
        HashMap<String, String> map = new HashMap<>(2);
        map.put("uri", request.getRequestURI());
        map.put("msg", "拒绝访问");
        response.setStatus(HttpServletResponse.SC_FORBIDDEN);
        response.setCharacterEncoding("utf-8");
        response.setContentType(MediaType.APPLICATION_JSON_VALUE);
        ObjectMapper objectMapper = new ObjectMapper();
        String resBody = objectMapper.writeValueAsString(map);
        PrintWriter printWriter = response.getWriter();
        printWriter.print(resBody);
        printWriter.flush();
        printWriter.close();
    }
}
package com.tuwer.config.handler;

import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.SneakyThrows;
import org.springframework.http.MediaType;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.oauth2.server.resource.InvalidBearerTokenException;
import org.springframework.security.web.AuthenticationEntryPoint;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashMap;

/**
 * <p>认证失败处理器</p>
 *
 * @author 土味儿
 * Date 2022/5/11
 * @version 1.0
 */
public class SimpleAuthenticationEntryPoint implements AuthenticationEntryPoint {
    @SneakyThrows
    @Override
    public void commence(HttpServletRequest request,
                         HttpServletResponse response,
                         AuthenticationException authException
    ) throws IOException, ServletException {
        HashMap<String, String> map = new HashMap<>(2);
        if (authException instanceof InvalidBearerTokenException) {
            // 令牌失效
            System.out.println("token失效");
            //todo token处理逻辑
        }
        map.put("uri", request.getRequestURI());
        map.put("msg", "认证失败");
        if (response.isCommitted()) {
            return;
        }
        response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
        response.setStatus(HttpServletResponse.SC_ACCEPTED);
        response.setCharacterEncoding("utf-8");
        response.setContentType(MediaType.APPLICATION_JSON_VALUE);
        ObjectMapper objectMapper = new ObjectMapper();
        String resBody = objectMapper.writeValueAsString(map);
        PrintWriter printWriter = response.getWriter();
        printWriter.print(resBody);
        printWriter.flush();
        printWriter.close();
    }
}
  • property(权限、令牌)属性类

    权限属性类:AuthProperty,通过application.yml来配置权限,避免在自动配置类中以硬编码的形式写入权限

package com.tuwer.config.property;

import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.util.CollectionUtils;

import java.util.Set;

/**
 * <p>权限属性类</p>
 *
 * @author 土味儿
 * Date 2022/9/2
 * @version 1.0
 */
@Data
@ConfigurationProperties(prefix = "resource-auth")
public final class AuthProperty {
    private Authority authority;

    /**
     * 权限
     */
    @Data
    public static class Authority {
        private Set<String> roles;
        private Set<String> scopes;
        private Set<String> auths;
    }

    /**
     * 组装权限字符串
     * 目的:给 hasAnyAuthority() 方法生成参数
     * @return
     */
    public String getAllAuth() {
        StringBuilder res = new StringBuilder();

        // 角色
        Set<String> roles = this.authority.roles;
        // 角色非空时
        if (!CollectionUtils.isEmpty(roles)) {
            for (String role : roles) {
                res.append(role).append("','");
            }
            // 循环结果后,生成类似:x ',' y ',' z ','
        }

        // 范围
        Set<String> scopes = this.authority.scopes;
        // 非空时
        if (!CollectionUtils.isEmpty(scopes)) {
            for (String scope : scopes) {
                res.append("SCOPE_" + scope).append("','");
            }
            // 循环结果后,生成类似:x ',' y ',' z ',' SCOPE_a ',' SCOPE_b ',' SCOPE_c ','
        }

        // 细粒度权限
        Set<String> auths = this.authority.auths;
        // 非空时
        if (!CollectionUtils.isEmpty(auths)) {
            for (String auth : auths) {
                res.append(auth).append("','");
            }
            // 循环结果后,生成类似:x ',' y ',' z ',' SCOPE_a ',' SCOPE_b ',' SCOPE_c ',' l ',' m ',' n ','
        }

        // 如果res不为空,去掉最后多出的三个字符 ','
        int len = res.length();
        if (len > 3) {
            res.delete(len - 3, len);
        }

        return res.toString();
    }
}

在这里插入图片描述

在这里插入图片描述

package com.tuwer.config.property;

import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;

/**
 * <p>属性配置类</p>
 *
 * @author 土味儿
 * Date 2022/5/11
 * @version 1.0
 */
@Data
@ConfigurationProperties(prefix = "jwt")
public class JwtProperty {
    /*
    ======= 配置示例 ======
    # 自定义 jwt 配置
    jwt:
        cert-info:
            # 证书存放位置
            public-key-location: myKey.cer
        claims:
            # 令牌的鉴发方:即授权服务器的地址
            issuer: http://os:9000
    */
    /**
     * 证书信息(内部静态类)
     * 证书存放位置...
     */
    private CertInfo certInfo;

    /**
     * 证书声明(内部静态类)
     * 发证方...
     */
    private Claims claims;

    @Data
    public static class Claims {
        /**
         * 发证方
         */
        private String issuer;
        /**
         * 有效期
         */
        //private Integer expiresAt;
    }

    @Data
    public static class CertInfo {
        /**
         * 证书存放位置
         */
        private String publicKeyLocation;
    }
}
  • 解码器自动配置类
package com.tuwer.config;

import com.nimbusds.jose.jwk.RSAKey;
import com.tuwer.config.property.JwtProperty;
import lombok.SneakyThrows;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.io.ClassPathResource;
import org.springframework.security.oauth2.core.DelegatingOAuth2TokenValidator;
import org.springframework.security.oauth2.core.OAuth2TokenValidator;
import org.springframework.security.oauth2.jwt.Jwt;
import org.springframework.security.oauth2.jwt.JwtDecoder;
import org.springframework.security.oauth2.jwt.JwtIssuerValidator;
import org.springframework.security.oauth2.jwt.NimbusJwtDecoder;

import javax.annotation.Resource;
import java.io.InputStream;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.security.interfaces.RSAPublicKey;
import java.util.Collection;

/**
 * <p>自定义jwt解码器</p>
 *
 * @author 土味儿
 * Date 2022/5/11
 * @version 1.0
 */
@EnableConfigurationProperties(JwtProperty.class)
@Configuration
public class JwtDecoderConfiguration {
    /**
     * 注入 JwtProperties 属性配置类
     */
    @Resource
    private JwtProperty jwtProperty;

    /**
     *  校验jwt发行者 issuer 是否合法
     *
     * @return the jwt issuer validator
     */
    @Bean
    JwtIssuerValidator jwtIssuerValidator() {
        return new JwtIssuerValidator(this.jwtProperty.getClaims().getIssuer());
    }

/*
    *
     *  校验jwt是否过期
     *
     * @return the jwt timestamp validator
*/
/*    @Bean
    JwtTimestampValidator jwtTimestampValidator() {
        System.out.println("检测令牌是否过期!"+ LocalDateTime.now());
        return new JwtTimestampValidator(Duration.ofSeconds((long) this.jwtProperties.getClaims().getExpiresAt()));
    }*/

    /**
     * jwt token 委托校验器,集中校验的策略{@link OAuth2TokenValidator}
     *
     * // @Primary:自动装配时当出现多个Bean候选者时,被注解为@Primary的Bean将作为首选者,否则将抛出异常
     * @param tokenValidators the token validators
     * @return the delegating o auth 2 token validator
     */
    @Primary
    @Bean({"delegatingTokenValidator"})
    public DelegatingOAuth2TokenValidator<Jwt> delegatingTokenValidator(Collection<OAuth2TokenValidator<Jwt>> tokenValidators) {
        return new DelegatingOAuth2TokenValidator<>(tokenValidators);
    }

    /**
     * 基于Nimbus的jwt解码器,并增加了一些自定义校验策略
     *
     * // @Qualifier 当有多个相同类型的bean存在时,指定注入
     * @param validator DelegatingOAuth2TokenValidator<Jwt> 委托token校验器
     * @return the jwt decoder
     */
    @SneakyThrows
    @Bean
    public JwtDecoder jwtDecoder(@Qualifier("delegatingTokenValidator")
                                         DelegatingOAuth2TokenValidator<Jwt> validator) {
        // 指定 X.509 类型的证书工厂
        CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
        // 读取cer公钥证书来配置解码器
        String publicKeyLocation = this.jwtProperty.getCertInfo().getPublicKeyLocation();
        // 获取证书文件输入流
        ClassPathResource resource = new ClassPathResource(publicKeyLocation);
        InputStream inputStream = resource.getInputStream();
        // 得到证书
        X509Certificate certificate = (X509Certificate) certificateFactory.generateCertificate(inputStream);
        // 解析
        RSAKey rsaKey = RSAKey.parse(certificate);
        // 得到公钥
        RSAPublicKey key = rsaKey.toRSAPublicKey();
        // 构造解码器
        NimbusJwtDecoder nimbusJwtDecoder = NimbusJwtDecoder.withPublicKey(key).build();
        // 注入自定义JWT校验逻辑
        nimbusJwtDecoder.setJwtValidator(validator);
        return nimbusJwtDecoder;
    }
}
  • 主自动配置类:安全权限等
package com.tuwer.config;

import com.tuwer.config.handler.SimpleAccessDeniedHandler;
import com.tuwer.config.handler.SimpleAuthenticationEntryPoint;
import com.tuwer.config.property.AuthProperty;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityCustomizer;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.oauth2.jwt.JwtClaimNames;
import org.springframework.security.oauth2.jwt.JwtDecoder;
import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationConverter;
import org.springframework.security.oauth2.server.resource.authentication.JwtGrantedAuthoritiesConverter;
import org.springframework.security.web.SecurityFilterChain;

import javax.annotation.Resource;

/**
 * <p>资源服务器配置</p>
 * 当解码器JwtDecoder存在时生效
 *
 * @author 土味儿
 * Date 2022/5/11
 * @version 1.0
 */
@ConditionalOnBean(JwtDecoder.class)
@EnableConfigurationProperties(AuthProperty.class)
@Configuration
public class AutoConfiguration {
    @Resource
    private AuthProperty authProperty;
    /**
     * 资源管理器配置
     *
     * @param http the http
     * @return the security filter chain
     * @throws Exception the exception
     */
    @Bean
    SecurityFilterChain jwtSecurityFilterChain(HttpSecurity http) throws Exception {
        // 拒绝访问处理器 401
        SimpleAccessDeniedHandler accessDeniedHandler = new SimpleAccessDeniedHandler();
        // 认证失败处理器 403
        SimpleAuthenticationEntryPoint authenticationEntryPoint = new SimpleAuthenticationEntryPoint();

        return http
                // security的session生成策略改为security不主动创建session即STALELESS
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
            .and()
                // 允许【pc客户端】或【其它微服务】访问
                .authorizeRequests()
                //.antMatchers("/**").hasAnyAuthority("SCOPE_client_pc","SCOPE_micro_service")
                // 从配置文件中读取权限信息
                .antMatchers("/**").hasAnyAuthority(authProperty.getAllAuth())
                // 其余请求都需要认证
                .anyRequest().authenticated()
             .and()
                // 异常处理
                .exceptionHandling(exceptionConfigurer -> exceptionConfigurer
                        // 拒绝访问
                        .accessDeniedHandler(accessDeniedHandler)
                        // 认证失败
                        .authenticationEntryPoint(authenticationEntryPoint)
                )
                // 资源服务
                .oauth2ResourceServer(resourceServer -> resourceServer
                        .accessDeniedHandler(accessDeniedHandler)
                        .authenticationEntryPoint(authenticationEntryPoint)
                        .jwt()
                )
                .build();
    }


    /**
     * JWT个性化解析
     *
     * @return
     */
    @Bean
    JwtAuthenticationConverter jwtAuthenticationConverter() {
        JwtAuthenticationConverter jwtAuthenticationConverter = new JwtAuthenticationConverter();
        JwtGrantedAuthoritiesConverter jwtGrantedAuthoritiesConverter = new JwtGrantedAuthoritiesConverter();
//        如果不按照规范  解析权限集合Authorities 就需要自定义key
//        jwtGrantedAuthoritiesConverter.setAuthoritiesClaimName("scopes");
//        OAuth2 默认前缀是 SCOPE_     Spring Security 是 ROLE_
//        jwtGrantedAuthoritiesConverter.setAuthorityPrefix("");
        jwtAuthenticationConverter.setJwtGrantedAuthoritiesConverter(jwtGrantedAuthoritiesConverter);
        // 用户名 可以放sub
        jwtAuthenticationConverter.setPrincipalClaimName(JwtClaimNames.SUB);
        return jwtAuthenticationConverter;
    }

    /**
     * 开放一些端点的访问控制
     * 不需要认证就可以访问的端口
     * @return
     */
    @Bean
    WebSecurityCustomizer webSecurityCustomizer() {
        return web -> web.ignoring().antMatchers(
                "/actuator/**"
        );
    }
}
  • spring.factories

指明自动配置类的地址,在 resources 目录下编写一个自己的 META-INF\spring.factories;有两个自动配置类,中间用逗号分开

注意点

如果同一个组中有多个starter,自动配置类名称不要相同;如果相同,将只有一个配置类生效,其余的将失效。

如:

  • starterA中:com.tuwer.config.AutoConfiguration

  • starterB中:就不要再用 com.tuwer.config.AutoConfiguration 名称,可以改为 com.tuwer.config.AutoConfigurationB

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
  com.tuwer.config.JwtDecoderConfiguration,\
  com.tuwer.config.AutoConfiguration
  • application.yml

令牌、权限的配置可以放在引用starter的资源服务中;如果每个资源服务的配置都一样,可以放在starter中

# 自定义 jwt 配置(校验jwt)
jwt:
  cert-info:
    # 公钥证书存放位置
    public-key-location: myjks.cer
  claims:
    # 令牌的鉴发方:即授权服务器的地址
    issuer: http://os.com:9000

# 自定义权限配置
resource-auth:
  # 权限
  authority:
    # 角色名称;不用加ROlE_,提取用户角色权限时,自动加
    roles:
    # 授权范围;不用加SCOPE_,保持与认证中心中定义的一致即可;
    # 后台自动加 SCOPE_
    scopes:
      - client_pc
      - micro_service
    # 细粒度权限
    auths:
  • 公钥

把认证中心的公钥文件myjks.cer放到resources目录下

4、install

把starter安装install到本地maven仓库中

在这里插入图片描述

在这里插入图片描述

三、使用starter

1、引入starter依赖

在资源服务中引入 tuwer-oauth2-config-spring-boot-starter

在这里插入图片描述

2、application.yml

在这里插入图片描述

3、删除资源服务中原文件

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/416127.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【案例实践】Python-GEE遥感云大数据分析、管理与可视化技术及多领域案例实践应用

查看原文>>>Python-GEE遥感云大数据分析、管理与可视化技术及多领域案例实践应用 目录 第一章、理论基础 第二章、开发环境搭建 第三章、遥感大数据处理基础 第四章、典型案例操作实践 第五章、输入输出及数据资产高效管理 第六章、云端数据论文出版级可视化 随…

图片懒加载及Vue自定义图片懒加载指令

文章目录监听滚动的方式IntersectionObserver方式自定义图片懒加载vue指令1自定义图片懒加载vue指令2lazyLoadImage.jsmain.js中注册指令组件中使用学习链接&#xff1a;前端必会的图片懒加载vue自定义指令实现图片懒加载监听滚动的方式 img的src先都用一张默认的图片&#xf…

论文推荐:DCSAU-Net,更深更紧凑注意力U-Net

这是一篇23年发布的新论文&#xff0c;论文提出了一种更深、更紧凑的分裂注意力的U-Net&#xff0c;该网络基于主特征守恒和紧凑分裂注意力模块&#xff0c;有效地利用了底层和高层语义信息。 DCSAU-Net 1、架构 DCSAU-Net 的编码器首先使用 PFC 策略从输入图像中提取低级语义…

适用于 Windows 11/1 0电脑的 8 款最佳免费数据恢复软件

在这个数字办公时代&#xff0c;我们总是在电脑前工作&#xff0c;处理海量数据&#xff0c;存储重要文件。然而&#xff0c;系统崩溃、病毒攻击或人为错误都会导致极度绝望的数据丢失。此时&#xff0c;专业的数据备份和恢复工具就是不幸者的救命稻草。因此&#xff0c;这篇文…

深入剖析Compose布局, 一步步教你打造自适应UI界面

理解Compose布局 Compose 是一种基于声明式编程的 Android UI 工具包&#xff0c;它将可组合的 UI 要素视为函数&#xff0c;并使用 Kotlin DSL 进行构建和组合。Compose 还提供了相应的布局系统和一组用于嵌套和组合 UI 要素的基本函数。 Compose 的核心布局系统由两个部分组…

Windows使用Dockers+battery historian踩坑记

1、首先&#xff0c;需要翻墙。 2、然后安装Dockers&#xff0c;网上好多博客说安装Docker Toolbox&#xff0c;我亲测无效&#xff0c;卸载后安装Docker for Windows&#xff0c;安装完成后打开&#xff0c;会提示&#xff1a; Hardware assisted virtualization and data e…

Promise这样理解更简单

一、Promise小白怎么用&#xff1f;从一个故事开始吧 1、先来一段废话故事 您是一名在古老迷失城市中探险的冒险家。您身处一间装饰华丽的房间中&#xff0c;四周布满了古老的壁画和雕塑。您发现有两个通道分别通向不同的方向&#xff0c;分别是&#xff1a;一个黑暗的通道和…

Hive源码阅读环境准备

源码地址 hive源码地址在github或gitee均可以下载&#xff0c;如果没有vpn工具&#xff0c;使用gitee网速更快点。 github地址为: https://github.com:edingbrugh/hive.gitgitee地址如下: https://gitee.com/apache/hive.git环境要求 本地或远程已经安装hivejdk 8maven 3.6…

高权限注入跨库注入

简介 上篇文章中我们讲述了如何进行手工注入&#xff0c;也通过墨者学院的靶场&#xff0c;真实的感受了SQL注入的感觉。这篇文章我们将继续介绍SQL注入。 高权限注入 含义 世界上有千千万万的网站&#xff0c;我们也都知道网站需要部署在服务器上&#xff0c;但是如果一台…

C++基础知识-----命名空间

本期开始我们来对C进行学习 目录 1.C关键字 2.命名空间 3.C的输入与输出 1.C关键字 C总计63个关键字&#xff0c;C语言32个关键字 asmdoifreturntrycontinueautodoubleinlineshorttypedefforbooldynamic_castintsignedtypeidpublicbreakelselongsizeoftypenamethrowcase…

摘得重磅奖项,发表精彩演讲,深度参编报告!美创闪耀CSA GCR大会

4月13日&#xff0c;第六届云安全联盟大中华区大会在上海举办&#xff0c;大会由联合国数字安全联盟、上海市经济和信息化委员会、上海市委网络安全和信息化委员会办公室、上海市普陀区人民政府指导&#xff0c;云安全联盟大中华区主办。 作为零信任数据安全践行者&#xff0c;…

java银行ATM机模拟系统dzkf94

目录 摘要 I Abstract II 第1章 绪论 1 1.1 ATM简介 1 1.2 ATM发展 1 1.3 开发意义 1 1.4 论文的组成 1 1.5 本章小结 2 第2章 系统分析 3 2.1 功能需求分析 3 2.2 业务流程分析 4 2.3 数据流程分析 5 2.4 本章小结 7 第3章 系统开发技…

车载网络 - Autosar网络管理 - 常用缩写

为了方便大家日常工作中的使用和交流&#xff0c;每块专业规范或者文章中&#xff0c;都会有或多或少的缩写使用&#xff0c;然而如果一段时间没使用&#xff0c;经常会忘记这些缩写到底代表的是什么意思&#xff0c;为了方便后续内容的介绍&#xff0c;也为了我自己后面忘记后…

【数据分析之道-NumPy(四)】numpy广播机制

文章目录 专栏导读1、广播机制2、一维数组和二维数组的广播3、二维数组和三维数组的广播4、标量和数组的广播5、形状不兼容的数组不能进行广播专栏导读 ✍ 作者简介:i阿极,CSDN Python领域新星创作者,专注于分享python领域知识。 ✍ 本文录入于《数据分析之道》,本专栏针对…

MySQL---数据类型

文章目录前言一、数据类型分类二、数值类型1.tinyint类型2.bit类型三、小数类型1.float2. decimal三、字符串类型1.char2.varchar3.char和varchar比较四、日期和时间类型五、enum和set我们如何找到性别是男或者女呢?我们如何找到爱好有rapper呢?总结前言 正文开始!!! 一、数…

MyBatis 批量插入的正确姿势

近日,项目中有一个耗时较长的Job存在CPU占用过高的问题,经排查发现,主要时间消耗在往MyBatis中批量插入数据。mapper configuration是用foreach循环做的,差不多是这样。 这个方法提升批量插入速度的原理是,将传统的: INSERT INTO `table1` (`field1`, `field2`) VALUES …

Linux服务器怎么关闭防火墙?

Linux服务器怎么关闭防火墙&#xff1f; 在很多情况下&#xff0c;防火墙都会组织一些端口号的通讯。 比如我们的tomcat&#xff0c;nginx&#xff0c;redis明明安装的没问题&#xff0c;但在外部就是访问不了&#xff0c;那很有可能就是防护墙的原因了。我是艾西&#xff0c;…

protobuf编码格式解析

示例 假如定义一个如下的protobuf类型 message Person {required string user_name 1;optional int64 favorite_number 2;repeated string interests 3; }将其赋值为: user_name : "Martin" favorite_number : 1337 interests:"daydrea…

pyLoad远程代码执行漏洞复现(CVE-2023-0297)

1、产品简介 pyLoad是一个用 Python 编写的免费和开源下载管理器&#xff0c;可用于NAS、下一代路由器、无头家庭服务器以及任何能够连接到互联网并支持 Python 编程语言的设备。 2、漏洞概述 pyLoad 存在代码注入漏洞&#xff0c;未经身份验证的攻击者可以通过滥用 js2py 功能…

c/c++:类型限定符,printf输出格式,putchar,scanf,getchar

c/c&#xff1a;类型限定符&#xff0c;printf输出格式&#xff0c;putchar&#xff0c;scanf&#xff0c;getchar 2022找工作是学历、能力和运气的超强结合体&#xff0c;遇到寒冬&#xff0c;大厂不招人&#xff0c;此时学会c的话&#xff0c; 我所知道的周边的会c的同学&am…