SpringSecurity配置及注解说明

【Spring Security注解详解】 Spring Security 是一个强大的、高度可定制的身份验证和访问控制框架,广泛用于Java应用程序中以确保安全。它提供了多种注解来简化安全控制的实现,特别是在方法级别的权限控制上。 阅读详情

一、配置准备

1、引入相关pom.xml
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
            <version>2.0.4.RELEASE</version>
        </dependency>
2、实现UserDetailsService,自定义赋予角色权限
//1、实现UserDetailsService接口
@Service("userDetailsService")
public class MyUserDetailsService implements UserDetailsService {
    //实现了mybatis-plus的BaseMapper
    @Autowired
    UsersMapper usersMapper;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        //2、在其中实现方法中写入用户的验证逻辑
        //权限不能为空,一般是从数据库中读
        //当用通过角色判断是否可以访问该页面时则需要给角色的名前+‘ROLE_’
        List<GrantedAuthority> auths = AuthorityUtils.commaSeparatedStringToAuthorityList("admin2,admin,manager,ROLE_admin");
		//Users是自定义的实体类
        QueryWrapper<Users> wrapper = new QueryWrapper<>();
        //条件
        wrapper.eq("username",username);
        //从数据库中查询用户
        Users users = usersMapper.selectOne(wrapper);

        if(users == null){
            throw new UsernameNotFoundException("用户名未找到");
        }

        return new User(users.getUsername(),new BCryptPasswordEncoder().encode(users.getPassword()),auths);
    }
}

3、SpringSecurity基础配置
@Configuration
@ComponentScan("com.security.securitydemo.entity")
public class SecurityConfigTest extends WebSecurityConfigurerAdapter {

    @Autowired
    private UserDetailsService userDetailsService;

    //1、配置数据源
    @Autowired
    private DataSource dataSource;
    //配置PersistentTokenRepository,该类用于配置token数据的处理方式
    //1、JdbcTokenRepositoryImpl 将token数据持久化(通过数据保存token)
    //2、InMemoryTokenRepositoryImpl 将token数据存在内存中
    @Bean
    public PersistentTokenRepository persistentTokenRepository(){
        JdbcTokenRepositoryImpl jdbcTokenRepository = new JdbcTokenRepositoryImpl();
        //配置数据源
        jdbcTokenRepository.setDataSource(dataSource);
        //自动生成存储token的表
        //jdbcTokenRepository.setCreateTableOnStartup(true);
        return jdbcTokenRepository;
    }

    public void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService).passwordEncoder(encoder());
    }
     /**
     * 配置页面访问权限及登录退出页面跳转,可根据自己的情况进行配置
     * @param httpSecurity
     * @throws Exception
     */
    public void configure(HttpSecurity httpSecurity) throws Exception {
//        httpSecurity.exceptionHandling().accessDeniedPage("/403");   /* 配置没有权限访问条状自定义页面 */
        //用户登录
        httpSecurity.formLogin()    /* 自定义自己编写的登录界面 */
                .loginPage("/login")   /* 登录页面设置 */
                .loginProcessingUrl("/user/login")  /* 登录访问路径 */
                .defaultSuccessUrl("/success")    /* 登陆成功后跳转路径 */
                .failureForwardUrl("/fail").permitAll()     /* 登陆失败跳转页面 */
                //权限设置
                .and().authorizeRequests()  /* 指定哪些url可以访问,那些不能访问 */
                .antMatchers("/test/index","/user/login").permitAll()    /* 设置那些路径不需要认证可以访问 */
                .antMatchers("/test/hello").hasAnyRole("admin")   /* 跟具已有角色判断是否可以访问这个页面 */
//                .antMatchers("/test/hello").hasRole("manager")     /* 跟具已有角色判断是否可以访问这个页面 */
//                .antMatchers("/test/hello").hasAnyAuthority("admin","manager") /* 只要有拥有其中一个权限即可访问这个页面 */
//                .antMatchers("/test/hello").hasAuthority("admin")    /* 当前用户登录只有具有admin权限才可以访问这个路径 */
                .anyRequest().authenticated()   /* 所有请求都可以访问 */
                //token配置
                .and().rememberMe().tokenRepository(persistentTokenRepository())    /* 2、设置PersistentTokenRepository */
                .tokenValiditySeconds(60)   /* 设置有效时长,单位秒 */
                .userDetailsService(userDetailsService);
                //.and().csrf().disable();     /* 关闭csrf防护 */
        //用户注销
        httpSecurity.logout()
                .logoutUrl("/logout")   /* 注销访问路劲 */
                .logoutSuccessUrl("/test/index").permitAll();   /* 注销成功跳转路径 */

    }
    
    @Bean
    public PasswordEncoder encoder(){
        return new BCryptPasswordEncoder();
    }
}
4、写好自己的登录页面及登录接口
@Controller
public class LoginController {
    @RequestMapping("/login")
    public String login(){
        return "login";
    }
    @RequestMapping("/success")
    public String success(){
        return "success";
    }
    @RequestMapping("/fail")
    public String fail(){
        return "fail";
    }
    @RequestMapping("/logout")
    public String logout(){
        return "login";
    }
}
5、写好用于测试的接口
@Controller
@RequestMapping("/test")
@EnableGlobalMethodSecurity(securedEnabled=true,prePostEnabled=true,jsr250Enabled = true)        /* 开启security注解 */
public class TestController {
    /**
     * @Secured 验证是否有其中一个角色,有才能调用该方法
     * @return
     */
    @Secured({"ROLE_manage","ROLE_admin"})  /* 只要拥有manage或admin其中一个角色就可以使用这个方法 */
    @RequestMapping("testSecured")
    @ResponseBody
    public String testSecured(){
        System.out.println("testSecured.....");
        return "testSecured ok";
    }

    /**
     * @RolesAllowed 验证是否有其中角色
     * 该注解需要开启jsr250Enabled
     * @return
     */
    @RolesAllowed({"ROLE_manage","ROLE_admin"})
    @RequestMapping("testRolesAllowed")
    @ResponseBody
    public String testRolesAllowed() {
        System.out.println("testRolesAllowed.....");
        return "testRolesAllowed ok";
    }

    /**
     * @PreAuthorize 在方法执行前进行权限验证
     * 在其中还可以使用其他的验证防范例如hasRole等
     * 这里是验证当前用户是否有admin权限
     * @return
     */
    @RequestMapping("testPreAuthorize")
    @ResponseBody
    @PreAuthorize("hasAnyAuthority('admin')")   /* 在方法调用之前验证是否有admin权限,没有则无法调用该方法 */
    public String testPreAuthorize(){
        System.out.println("PreAuthorize......");
        return "PreAuthorize ok";
    }

    /**
     * @PostAuthorize 在方法执行后再进行权限验证
     * 可以使用内置的表达式returnObject表示方法的返回值
     * @return
     */
    @PostAuthorize("returnObject.equals('PostAuthorize ok')")   /* 在方法执行后再进行权限验证,适合验证带有返回值的权限 */
    @RequestMapping("testPostAuthorize")
    @ResponseBody
    public String testPostAuthorize(){
        System.out.println("PostAuthorize......");
        return "PostAuthorize ok";
    }

    /**
     * @PostFilter 过滤返回的结果
     * 这里指的是只返回username为zhangsan的内容
     * @return
     */
    @PreAuthorize("hasAnyAuthority('admin')")
    @PostFilter("filterObject.username == 'zhansan'")    /* 如果有权限满足条件则过滤响应结果 */
    @ResponseBody
    @RequestMapping("testPostFilter")
    public List<Users> testPostFilter(){
        List<Users> list = new ArrayList<>();
        list.add(new Users(1,"zhansan","123"));
        list.add(new Users(2,"lisi","123"));
        System.out.println(list);
        return list;    //[{"id":1,"username":"zhansan","password":"123"}]
    }

    /**
     * @PreFilter 过滤的是传进来的参数
     * 这里指传进来Users列表中Users的id>2才能被传进来
     * @param list1
     * @return
     */
    @RequestMapping("testPreFilter")
    @PreAuthorize("hasAnyAuthority('admin')")
    @PreFilter(value = "filterObject.id %2 == 0")   /* 满足条件,对于参数数据进行过滤处理 */
    @ResponseBody
    public List<Users> testPreFilter(List<Users> list1){
        List<Users> list2 = new ArrayList<>();
        list2.add(new Users(10,"十","12345"));
        list1.addAll(list2);
        return list1;
    }
}

二、注解说明

在使用springsecurity注解之前需要在类上开启springsecurity的注解

@EnableGlobalMethodSecurity(securedEnabled=true,prePostEnabled=true,jsr250Enabled = true)        /* 开启security注解 */

权限均参照以上我在MyUserDetailsService中配置的权限,及以上在接口配置的注解

List<GrantedAuthority> auths = AuthorityUtils.commaSeparatedStringToAuthorityList("admin2,admin,manager,ROLE_admin");
1、@Secured

验证是否有其中的一个角色,有才能调用该接口
注意:在使用该接口前必须在 @EnableGlobalMethodSecurity 注解中添加securedEnabled=true才能使该注解生效

@Secured({"ROLE_manage","ROLE_admin"})

演示效果
在这里插入图片描述

2、@RolesAllowed

类似于@Secured 验证是否有其中的一个角色,有才能调用该接口
注意:该注解需要开启jsr250Enabled

@RolesAllowed({"ROLE_manage","ROLE_admin"})

演示效果
在这里插入图片描述

3、@PreAuthorize

注意:该注解需要开启prePostEnabled=true
在方法执行前进行权限验证,主要是配合以下的验证方法对用户进行权限验证
hasRole(“manager”)、hasAnyAuthority(“admin”,“manager”)、hasAuthority(“admin”)、hasAnyRole(“admin”)

@PreAuthorize("hasAnyAuthority('admin')")

演示效果
在这里插入图片描述

4、@PostAuthorize

注意:该注解需要开启prePostEnabled=true
在方法执行后对返回值进行权限验证
可以使用内置的表达式returnObject表示方法的返回值

以下演示返回值均是之前代码的返回值,这里的返回值是PostAuthorize ok

@PostAuthorize("returnObject.equals('PostAuthorize ok')")

演示效果
在这里插入图片描述

@PostAuthorize("returnObject.equals('PostAuthorize no')")

演示效果(该页面为自定义的403无权限提示页面)
在这里插入图片描述

5、@PostFilter

过滤返回的结果
filterObject是执行过滤操作的内置对象。

@PostFilter("filterObject.username == 'zhansan'") 	//这里指的是只返回username为zhangsan的内容

演示效果
返回全部内容如下所示

    public List<Users> testPostFilter(){
        List<Users> list = new ArrayList<>();
        list.add(new Users(1,"zhansan","123"));
        list.add(new Users(2,"lisi","123"));
        System.out.println(list);
        return list;    //[{"id":1,"username":"zhansan","password":"123"}]
    }

在这里插入图片描述

6、@PreFilter

过滤的是传进来的参数
filterObject是执行过滤操作的内置对象。

后续补充。。。。。

解锁Spring Security注解鉴权与CAS整合实践 在这个例子中,我们使用SimpleGrantedAuthority表示自定义权限,并在构造CustomUserDetails时进行相应的处理。在上述配置中,我们通过authenticationUserDetailsService()方法返回了一个自定义的AuthenticationUserDetailsService实现,用于从CAS验证结果中构建CustomUserDetails对象。在接口层面,我们可以使用Spring Security提供的注解鉴权功能,结合CAS验证结果的权限信息进行精细控制。 阅读详情

相关推荐

SpringSecurity之跨域

CORS(Cross-Origin Resource Sharing)是由W3C制定的一种跨域资源共享技术标准,其目的就是为了解决前端的跨域请求。在JavaEE开发中,最常见的前端跨域请求解决方案是早起的JSONP,但是JSONP只支持GET请求,这是一个很大的缺陷,而CORS则支持多种HTTP请求方法,也是目前主流的跨域解决方案。CORS中新增了一组HTTP请求头字段,通过这些字段,服务器高炉浏览器,哪些网站通过浏览器有权限访问哪些资源。

m0_74825526的博客 1015

Spring——Security安全框架之注解使用

文章目录前言本次测试注解介绍注解使用@Secured@PreAuthorize@PostAuthorize@PostFilter@PreFilter代码下载 前言 之前security中,针对配置项进行了相关的配置和测试。 但是这些都是基于在security.config.MyConfig#configure(org.springframework.security.config.annotation.web.builders.HttpSecurity)中进行对应请求的权限限制。 如果是多个请求,各个有

专注写bug 5972

SpringSecurity——基于角色权限控制和资源权限控制

直接在resources/static/error下面配置页面即可Spring Boot 内置了一个默认的错误处理机制。当应用返回错误状态码(例如 403)时,Spring Boot 会自动查找与该状态码匹配的错误页面。如果在下存在对应名称(如403.html)的页面,系统就会直接返回该静态页面,而无需额外配置或编写代码。这种设计符合 Spring Boot “约定优于配置” 的理念,简化了错误处理的配置过程。

gege_0606的博客 1538

30个SpringSecurity注解:注解架构设计与应用详解(必须收藏)

Spring Security 通过一系列注解简化了安全配置,使得开发者能够以声明式的方式实现安全控制。这些注解包括用于启用安全特性的 `@EnableWebSecurity` 和 `@EnableGlobalMethodSecurity`,以及用于方法级别的安全控制,如 `@PreAuthorize` 和 `@PostAuthorize`。此外,`@EnableOAuth2Client` 和 `@EnableOAuth2ResourceServer` 等注解支持 OAuth2 认证和资源保护。这些注解共同

肖哥弹架构博客 1846

Autosar结合simulink的汽车应用层软件开发实例

本文基于汽车应用开发案例,并结合Autosar相关知识,生成具有Autosar标准的汽车应用层开发代码,以供学习和参考。以上就是本篇内容,主要是利用Simulink创建Autosar接口并进行端口映射的方法。

m0_64899535的博客 2153

ComfyUI全自动换装工作流:从零到一的实战指南

本文提供了一份详细的ComfyUI全自动换装工作流实战指南。从环境配置、模型准备到核心工作流架构的逐步拆解,手把手教你搭建一条高效的AI换装流水线。文章深入解析了从输入、预处理、融合到输出的四步核心逻辑,并分享了关键参数调优与进阶技巧,旨在帮助电商从业者、内容创作者及AI爱好者轻松实现高质量、高效率的“一键换装”。

weixin_29198045的博客 901

5.Spring Security安全注解(@PreAuthorize、@PostAuthorize、@PostFilter、@PreFilter)

Spring Security默认是禁用注解的,要想开启注解,需要在继承WebSecurityConfigurerAdapter的类上加@EnableGlobalMethodSecurity注解,并在该类中将AuthenticationManager定义为Bean如果要启用基于注解的方法安全性,要在配置类上使用**@EnableGlobalMethodSecurity**设置了securedEnabled = true,此时Spring将会创建一个切点,并将带有@Secured注解的方法防入切面中。

相互学习 共同进步 1775

C++开发基础之掌握常用的三种异步编程模型

以上是三种常见的C++异步编程模型,每种模型都有其适用的场景和特点。根据具体需求,你可以选择合适的模型来进行异步编程。

dotnet研习社 2177

SpringSecurity请求授权规则配置与注解使用说明

SringSecurity请求授权规则配置与注解使用说明 这里主要是重写WebSecurityConfigurerAdapter 的configure方法。 ① 自定义登录 这里与 都可以实现认证成功后跳转的效果,不过具体用法上有所区别。通常建议使用,至于具体区别后面另开章节学习。

小小默:进无止境 1004

从零到一:基于Rocky Linux 9的Kubernetes高可用集群部署实战

本文提供了一份基于Rocky Linux 9操作系统,从零开始部署Kubernetes高可用集群的完整实战指南。详细讲解了包括系统初始化、容器运行时配置、使用kubeadm工具进行集群初始化、节点加入以及Calico网络插件安装在内的核心步骤,并针对国内网络环境提供了镜像加速等优化方案,旨在帮助读者构建一个稳定可靠的生产级K8s环境。

weixin_29197835的博客 140

Coze平台智能体开发实战:打造测试工程师的AI助手

智能体是具备特定身份和能力的AI实体,由大语言模型(LLM)驱动,并通过插件、知识库和工作流扩展其能力。明确的角色定位:可以设定特定身份和专业领域扩展能力:通过插件连接外部工具和服务记忆能力:通过知识库存储和检索专属信息流程化处理:通过工作流执行复杂多步任务通过Coze平台创建测试工程师智能体,可以显著提升测试效率和质量。明确的角色定位:聚焦测试工程师的实际需求丰富的知识库:提供准确的领域知识支持合适的工具集成:通过插件连接现有工具链持续迭代优化:根据反馈不断改进智能体行为自动化测试生成。

hogwarts_beibei的博客 1005

【SpringSecurity】SpringSecurity安全框架授权

所以我们在项目中只需要把当前登录用户的权限信息也存入 Authentication,然后设置我们的资源所需要的权限即可。写 UserDetailsServiceImzho 中,在查询出用户后还要获取对应的权限信息,封装到 UserDetails 中返回。在后台进行用户权限的判断,判断当前用户是否有相应的权限,必须具有所需权限才能进行相应的操作。修改 UserDetails 的实现类 LoginUser,让其能封装权限信息。基于角色的权限控制。把权限信息写死封装到 UserDetails 中进行测试。

m0_66584716的博客 763

Ultralytics YOLO模块自定义与替换实战技巧

本文详细介绍了在Ultralytics YOLO框架中进行模块自定义与替换的实战技巧。通过从零开始添加全新模块(如注意力模块)到进阶替换现有模块(如增强版卷积),并涵盖模块注册、YAML配置、模型融合及ONNX导出等关键步骤,帮助开发者深度定制YOLO模型,以应对复杂检测任务与部署需求。

numpy6sculptor的博客 931

SpringSecurity-授权学习日志

SpringSecurity提供方便的授权功能,有俩种实现配置方式,同时原理也不复杂

2401_87808951的博客 1685

医学影像处理实战:用SimpleITK将CT数据重采样到统一尺寸(附完整代码)

本文针对医学影像分析中多源CT数据尺寸不一致导致深度学习模型训练失败的问题,提供了基于SimpleITK的实战解决方案。通过深入解析图像尺寸与间距的关系,详细阐述了如何通过调整体素间距进行重采样,而非简单补零,从而在保持图像物理尺寸不变的前提下,将数据统一到固定尺寸,确保输入网络的3D数据空间对齐且解剖信息准确。

weixin_29062671的博客 271

超大规模系统(千万级用户)中实现字段级权限控制

摘要:本文提出了一套分布式架构下的字段级权限优化方案,结合RBAC+ABAC混合模型与技术手段实现性能与安全的平衡。方案包括:1)权限模型优化,采用RBAC预计算基础权限与ABAC动态校验敏感字段;2)数据层优化,实现动态字段过滤与加密存储;3)多级缓存策略与预计算机制提升性能;4)分布式架构设计,通过网关校验和策略引擎集群保证扩展性。最终在千万级用户系统中实现99.9%可用性,权限校验延迟控制在50ms以内。

从技术实践立足,从项目管理方法论延伸思考 1353

springBoot整合springSecurity基于RBAC权限验证

学学springSecurity的认证授权框架,后续整合一下JWT 先说一下基于RBAC权限管理的思路 在数据库中配置用户权限 在每个接口上使用注解的形式说明接口需要用户拥有那个权限才能访问 SpringSecurity使用拦截请求的方式对当前用户拥有的权限和接口需要的权限进行比对,包含则放行,不包含则拦截 导入SpringSecurity的maven坐标 <dependency> <groupId>org.springframework.boot

qq_1641486826的博客 2855

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

SpringSecurity使用介绍

Spring Security是基于Spring的安全框架,提供了包含认证和授权的落地方案;Spring Security底层充分利用了Spring IOC和AOP功能,为企业应用系统提供了声明式安全访问控制解决方案;SpringSecurity可在Web请求级别和方法调用级别处理身份认证和授权,为应用系统提供声明式的安全访问控制功能;官网地址: https://spring.io/projects/spring-security。

几许的博客 1220

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

十分钟带你入门SpringSecurity

🏡  博客首页:派 大 星 ⛳️  欢迎关注  ❤️ 点赞  🎒 收藏  ✏️ 留言 🎢  本文由派大星原创编撰 🚧  系列专栏:《安全框架》 🎈   技术要学以致用,而不仅停留在学习阶段 目录🍉  学前测试🍒  权限管理中的相关概念① 添加一个控制器进行访问② SpringSecurity基本原理③ 过滤器如何进行加载的?④ UserDetailsServic.

派大星的博客 3463

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

SpringSecurity登录之权限控制二

1. 继上一篇SpringSecurity登录拦截后,本篇继续讲如何使不同的账户角色,有不同的访问权限。 2.在SpringSecurityConfig类中再添加一个账户,具有USER权限,代码如下: @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { ...

一点博客 339

SpringBoot整合SpringSecurity-元一软件

Spring Security是一个用于身份认证和授权的安全框架,主要提供两大核心功能:认证(Authentication)验证用户身份,如用户名密码登录;授权(Authorization)控制用户对资源的访问权限。整合Spring Boot时需引入相关依赖,并通过配置类继承WebSecurityConfigurerAdapter来自定义认证(内存或数据库方式)和授权规则。默认提供基础登录和注销功能,实际开发中需根据业务需求配置密码加密、权限管理等。微服务环境下推荐基于资源的访问控制(RBAC)。

355

认证鉴权框架SpringSecurity-3--代码集成_认证篇1(重写UserDetailsService示例)

如果配置类和注解都限制了接口权限,想要成功访问接口,就需要两者的条件都满足才可以,有一个不满足都无法访问。优先经过是HttpSecurity 的配置,其次校验是接口上注解。学海无涯苦作舟!!!

weisian的博客 1001

Knife4j接口文档

swagger接口文档

qq_53318060的博客 623

随手记录第十话 -- 升级SpringBoot3.0 + JDK17的踩坑记录

随着有些jar包的升级,JDK1.8已经不是最稳定的版本了。前段时间接触到Web3相关,jar包的编译最低要JDK13了,碰巧另一个使用Kotlin写的jar包依赖需要17了,那就直接上17吧,同时Springboot也上到3.0。

生生不息,则源源不断 1219

@Secured()、 @PreAuthorize() 、 @RolesAllowed()

在Spring security的使用中,为了对方法进行权限控制,通常采用的三个注解,就是@Secured()、@PreAuthorize()、@RolesAllowed()。 示例,修改用户密码必须是ADMIN权限,可以用三种方法: @Secured({"ROLE_ADMIN"}) public void changePassword(String username, Str...

atu99602的博客 764

@EnableGlobalMethodSecurity和@EnableWebSecurity的区别及使用场景

EnableGlobalMethodSecurity和@EnableWebSecurity是Spring Security框架中的两个重要注解,它们各自在Spring应用的安全性方面发挥着不同的作用。下面是这两个注解的区别以及使用场景和举例说明。

m0_70276286的博客 1560
上一篇: dockerfile基本内容笔记
magicproblem
博客等级 码龄7年 22粉丝 59原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值