Spring Shiro基础组件 Configuration

相关阅读

简介

Spring Shiro的配置器主要分为四类:

  1. 管理Annotation的配置器;
  2. 管理Bean的配置器;
  3. Filter的配置器;
  4. Bean的配置器;

管理Annotation的配置器

AbstractShiroAnnotationProcessorConfiguration

简介

Spring Shiro 管理Annotation的基础配置器,创建注解处理器;

核心代码

/**
 * 创建DefaultAdvisorAutoProxyCreator Bean
 */
protected DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
    // 基于BeanFactory中所有候选Advisor创建AOP代理的Bean后置处理器
    // 可以通过usePrefix和advisorBeanNamePrefix过滤Bean名称不符合的Advisor
    return new DefaultAdvisorAutoProxyCreator();
}
 
/**
 * 创建AuthorizationAttributeSourceAdvisor Bean
 */
protected AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
    // 拦截并处理Shiro框架授权注解的切面
    // 使用AopAllianceAnnotationsAuthorizingMethodInterceptor作为通知
    // 切点为带有Shiro框架授权注解的方法
    AuthorizationAttributeSourceAdvisor advisor = new AuthorizationAttributeSourceAdvisor();
 
    // 配置AuthorizationAttributeSourceAdvisor Bean
    advisor.setSecurityManager(securityManager);
    return advisor;
}

ShiroAnnotationProcessorConfiguration

简介

Spring Shiro 管理Annotation的配置器,简单调用父类方法创建注解处理器;

核心代码

/**
 * 创建DefaultAdvisorAutoProxyCreator Bean
 */
@Bean
@DependsOn("lifecycleBeanPostProcessor")
protected DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
    // 该Bean后置处理器会实现AOP功能
    // 为包含带有权限注解的方法的Bean创建代理,增加AuthorizationAttributeSourceAdvisor切面
    return super.defaultAdvisorAutoProxyCreator();
}
 
/**
 * 创建AuthorizationAttributeSourceAdvisor Bean
 */
@Bean
protected AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
    // 每执行代理Bean的方法前都会执行该切面的处理逻辑
    // 判断符合权限注解的的条件才可以执行原方法,否则抛出异常
    return super.authorizationAttributeSourceAdvisor(securityManager);
}

管理Bean的配置器

AbstractShiroBeanConfiguration

简介

Spring Shiro 管理Bean的基础配置器,创建Bean的后置处理器;

核心代码

/**
 * 创建LifecycleBeanPostProcessor Bean
 */
protected LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
    // LifecycleBeanPostProcessor会自动调用那些实现Initializable/Destroyable接口的类的实例的init()/destroy()方法
    // 而不需要指定bean的init-method/destroy-method属性
    // 因为无法确定init()/destroy()方法是否已被调用
    // 所以不要手动或者通过bean的init-method/destroy-method属性调用这些方法
    return new LifecycleBeanPostProcessor();
}
 
/**
 * 创建EventBus Bean
 */
protected EventBus eventBus() {
    // 默认使用DefaultEventBus发布事件到已注册的监听器,管理监听器
    return new DefaultEventBus();
}
 
/**
 * 创建ShiroEventBusBeanPostProcessor Bean
 */
protected ShiroEventBusBeanPostProcessor shiroEventBusAwareBeanPostProcessor() {
    // ShiroEventBusBeanPostProcessor会自动将EventBus注入到实现了EventBusAware接口的类的实例
    // 会自动将含有带有@Subscribe注解的方法的类的实例注册到EventBus
    return new ShiroEventBusBeanPostProcessor(eventBus());
}

ShiroBeanConfiguration

简介

Spring Shiro 管理Bean的配置器,简单调用父类方法创建Bean的后置处理器;

核心代码

/**
 * 创建LifecycleBeanPostProcessor Bean
 */
@Bean
@Override
public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
    return super.lifecycleBeanPostProcessor();
}
 
/**
 * 创建EventBus Bean
 */
@Bean
@Override
protected EventBus eventBus() {
    return super.eventBus();
}
 
/**
 * 创建ShiroEventBusBeanPostProcessor Bean
 */
@Bean
@Override
public ShiroEventBusBeanPostProcessor shiroEventBusAwareBeanPostProcessor() {
    return super.shiroEventBusAwareBeanPostProcessor();
}

Filter的配置器

AbstractShiroWebFilterConfiguration

简介

Shiro Web Filter基础配置器,创建Shiro框架需要的FilterFactoryBean和默认过滤器集合;

核心代码

@Autowired
protected SecurityManager securityManager;
 
@Autowired
protected ShiroFilterChainDefinition shiroFilterChainDefinition;
 
@Autowired(required = false)
protected Map<String, Filter> filterMap;
 
// 登录URL
@Value("#{ @environment['shiro.loginUrl'] ?: '/login.jsp' }")
protected String loginUrl;
 
// 成功URL
@Value("#{ @environment['shiro.successUrl'] ?: '/' }")
protected String successUrl;
 
// 授权失败URL
@Value("#{ @environment['shiro.unauthorizedUrl'] ?: null }")
protected String unauthorizedUrl;
 
/**
 * 创建全局过滤器集合 Bean
 */
protected List<String> globalFilters() {
    // 默认只有InvalidRequestFilter
    return Collections.singletonList(DefaultFilter.invalidRequest.name());
}
 
/**
 * 创建ShiroFilterFactoryBean Bean
 */
protected ShiroFilterFactoryBean shiroFilterFactoryBean() {
    ShiroFilterFactoryBean filterFactoryBean = new ShiroFilterFactoryBean();
 
    // 配置ShiroFilterFactoryBean Bean
    filterFactoryBean.setLoginUrl(loginUrl);
    filterFactoryBean.setSuccessUrl(successUrl);
    filterFactoryBean.setUnauthorizedUrl(unauthorizedUrl);
 
    filterFactoryBean.setSecurityManager(securityManager);
    filterFactoryBean.setGlobalFilters(globalFilters());
    filterFactoryBean.setFilterChainDefinitionMap(shiroFilterChainDefinition.getFilterChainMap());
    filterFactoryBean.setFilters(filterMap);
 
    return filterFactoryBean;
}

ShiroWebFilterConfiguration

简介

Shiro Web Filter基础配置器,简单调用父类方法创建Shiro框架需要的FilterFactoryBean和默认过滤器集合;

核心代码

/**
 * 创建ShiroFilterFactoryBean Bean
 */
@Bean
@Override
protected ShiroFilterFactoryBean shiroFilterFactoryBean() {
    return super.shiroFilterFactoryBean();
}
 
/**
 * 创建全局过滤器集合 Bean
 */
@Bean(name = "globalFilters")
protected List<String> globalFilters() {
    return super.globalFilters();
}

Bean的配置器

AbstractShiroConfiguration

简介

Shiro 基础配置器,创建Shiro框架需要的Bean

核心代码

// 缓存管理器
@Autowired(required = false)
protected CacheManager cacheManager;
 
// 角色权限解析器
@Autowired(required = false)
protected RolePermissionResolver rolePermissionResolver;
 
// 权限解析器
@Autowired(required = false)
protected PermissionResolver permissionResolver;
 
// 事件总线
@Autowired
protected EventBus eventBus;
 
// 删除失效会话标识
@Value("#{ @environment['shiro.sessionManager.deleteInvalidSessions'] ?: true }")
protected boolean sessionManagerDeleteInvalidSessions;
 
/**
 * 创建SessionsSecurityManager Bean
 */
protected SessionsSecurityManager securityManager(List<Realm> realms) {
    // 默认为DefaultSecurityManager
    SessionsSecurityManager securityManager = createSecurityManager();
 
    // 配置SessionsSecurityManager Bean
    securityManager.setAuthenticator(authenticator());
    securityManager.setAuthorizer(authorizer());
    securityManager.setRealms(realms);
    securityManager.setSessionManager(sessionManager());
    securityManager.setEventBus(eventBus);
 
    if (cacheManager != null) {
        securityManager.setCacheManager(cacheManager);
    }
 
    return securityManager;
}
 
/**
 * 创建SessionManager Bean
 */
protected SessionManager sessionManager() {
    // 默认为DefaultSessionManager
    DefaultSessionManager sessionManager = new DefaultSessionManager();
 
    // 配置SessionManager Bean
    sessionManager.setSessionDAO(sessionDAO());
    sessionManager.setSessionFactory(sessionFactory());
    sessionManager.setDeleteInvalidSessions(sessionManagerDeleteInvalidSessions);
    return sessionManager;
}
 
/**
 * 创建SessionsSecurityManager Bean
 */
protected SessionsSecurityManager createSecurityManager() {
    // 默认为DefaultSecurityManager
    DefaultSecurityManager securityManager = new DefaultSecurityManager();
 
    // 配置SessionsSecurityManager Bean
    securityManager.setSubjectDAO(subjectDAO());
    securityManager.setSubjectFactory(subjectFactory());
 
    RememberMeManager rememberMeManager = rememberMeManager();
    if (rememberMeManager != null) {
        securityManager.setRememberMeManager(rememberMeManager);
    }
 
    return securityManager;
}
 
/**
 * 创建RememberMeManager Bean
 */
protected RememberMeManager rememberMeManager() {
    // 默认不开启RememberMe服务,故直接返回null
    return null;
}
 
/**
 * 创建SubjectDAO Bean
 */
protected SubjectDAO subjectDAO() {
    // 默认为DefaultSubjectDAO
    DefaultSubjectDAO subjectDAO = new DefaultSubjectDAO();
 
    // 配置SubjectDAO Bean
    subjectDAO.setSessionStorageEvaluator(sessionStorageEvaluator());
    return subjectDAO;
}
 
/**
 * 创建SessionStorageEvaluator Bean
 */
protected SessionStorageEvaluator sessionStorageEvaluator() {
    // 默认为DefaultSessionStorageEvaluator
    return new DefaultSessionStorageEvaluator();
}
 
/**
 * 创建SubjectFactory Bean
 */
protected SubjectFactory subjectFactory() {
    // 默认为DefaultSubjectFactory
    return new DefaultSubjectFactory();
}
 
/**
 * 创建SessionFactory Bean
 */
protected SessionFactory sessionFactory() {
    // 默认为SimpleSessionFactory
    return new SimpleSessionFactory();
}
 
/**
 * 创建SessionDAO Bean
 */
protected SessionDAO sessionDAO() {
    // 默认为MemorySessionDAO
    return new MemorySessionDAO();
}
 
/**
 * 创建Authorizer Bean
 */
protected Authorizer authorizer() {
    // 默认为ModularRealmAuthorizer
    ModularRealmAuthorizer authorizer = new ModularRealmAuthorizer();
 
    // 配置Authorizer Bean
    if (permissionResolver != null) {
        authorizer.setPermissionResolver(permissionResolver);
    }
 
    if (rolePermissionResolver != null) {
        authorizer.setRolePermissionResolver(rolePermissionResolver);
    }
 
    return authorizer;
}
 
/**
 * 创建AuthenticationStrategy Bean
 */
protected AuthenticationStrategy authenticationStrategy() {
    // 默认为AtLeastOneSuccessfulStrategy
    return new AtLeastOneSuccessfulStrategy();
}
 
/**
 * 创建Authenticator Bean
 */
protected Authenticator authenticator() {
    // 默认为ModularRealmAuthenticator
    ModularRealmAuthenticator authenticator = new ModularRealmAuthenticator();
 
    // 配置Authenticator Bean
    authenticator.setAuthenticationStrategy(authenticationStrategy());
    return authenticator;
}
 
/**
 * 创建Realm Bean
 */
protected Realm iniRealmFromLocation(String iniLocation) {
    // 默认为IniRealm
    Ini ini = Ini.fromResourcePath(iniLocation);
    return new IniRealm( ini );
}

ShiroConfiguration

简介

Shiro 配置器,简单调用父类方法创建Shiro框架需要的Bean

核心代码

/**
 * 创建SessionsSecurityManager Bean
 */
@Bean
@Override
protected SessionsSecurityManager securityManager(List<Realm> realms) {
    return super.securityManager(realms);
}
 
/**
 * 创建SessionManager Bean
 */
@Bean
@Override
protected SessionManager sessionManager() {
    return super.sessionManager();
}
 
/**
 * 创建SubjectDAO Bean
 */
@Bean
@Override
protected SubjectDAO subjectDAO() {
    return super.subjectDAO();
}
 
/**
 * 创建SessionStorageEvaluator Bean
 */
@Bean
@Override
protected SessionStorageEvaluator sessionStorageEvaluator() {
    return super.sessionStorageEvaluator();
}
 
/**
 * 创建SubjectFactory Bean
 */
@Bean
@Override
protected SubjectFactory subjectFactory() {
    return super.subjectFactory();
}
 
/**
 * 创建SessionFactory Bean
 */
@Bean
@Override
protected SessionFactory sessionFactory() {
    return super.sessionFactory();
}
 
/**
 * 创建SessionDAO Bean
 */
@Bean
@Override
protected SessionDAO sessionDAO() {
    return super.sessionDAO();
}
 
/**
 * 创建Authorizer Bean
 */
@Bean
@Override
protected Authorizer authorizer() {
    return super.authorizer();
}
 
/**
 * 创建AuthenticationStrategy Bean
 */
@Bean
@Override
protected AuthenticationStrategy authenticationStrategy() {
    return super.authenticationStrategy();
}
 
/**
 * 创建Authenticator Bean
 */
@Bean
@Override
protected Authenticator authenticator() {
    return super.authenticator();
}
 
/**
 * 创建Realm Bean
 */
@Bean
@Override
protected RememberMeManager rememberMeManager() {
    return super.rememberMeManager();
}

AbstractShiroWebConfiguration

简介

基于Shiro 基础配置器,创建Web环境下需要的Bean

核心代码

// 开启Session ID 存入Cookie标识
@Value("#{ @environment['shiro.sessionManager.sessionIdCookieEnabled'] ?: true }")
protected boolean sessionIdCookieEnabled;
 
// 开启重写Session ID URL标识
@Value("#{ @environment['shiro.sessionManager.sessionIdUrlRewritingEnabled'] ?: false }")
protected boolean sessionIdUrlRewritingEnabled;
 
// 使用本地SessionManager标识
@Value("#{ @environment['shiro.userNativeSessionManager'] ?: false }")
protected boolean useNativeSessionManager;
 
// Session ID Cookie 名称
@Value("#{ @environment['shiro.sessionManager.cookie.name'] ?: T(org.apache.shiro.web.servlet.ShiroHttpSession).DEFAULT_SESSION_ID_NAME }")
protected String sessionIdCookieName;
 
// Session ID Cookie 最大存活时长
@Value("#{ @environment['shiro.sessionManager.cookie.maxAge'] ?: T(org.apache.shiro.web.servlet.SimpleCookie).DEFAULT_MAX_AGE }")
protected int sessionIdCookieMaxAge;
 
// Session ID Cookie 域名
@Value("#{ @environment['shiro.sessionManager.cookie.domain'] ?: null }")
protected String sessionIdCookieDomain;
 
// Session ID Cookie 路径
@Value("#{ @environment['shiro.sessionManager.cookie.path'] ?: null }")
protected String sessionIdCookiePath;
 
// Session ID Cookie Secure
@Value("#{ @environment['shiro.sessionManager.cookie.secure'] ?: false }")
protected boolean sessionIdCookieSecure;
 
// Session ID Cookie SameSite
@Value("#{ @environment['shiro.sessionManager.cookie.sameSite'] ?: T(org.apache.shiro.web.servlet.Cookie.SameSiteOptions).LAX  }")
protected Cookie.SameSiteOptions sessionIdCookieSameSite;
 
// RememberMe Cookie 名称
@Value("#{ @environment['shiro.rememberMeManager.cookie.name'] ?: T(org.apache.shiro.web.mgt.CookieRememberMeManager).DEFAULT_REMEMBER_ME_COOKIE_NAME }")
protected String rememberMeCookieName;
 
// RememberMe Cookie 最大存活时长
@Value("#{ @environment['shiro.rememberMeManager.cookie.maxAge'] ?: T(org.apache.shiro.web.servlet.Cookie).ONE_YEAR }")
protected int rememberMeCookieMaxAge;
 
// RememberMe Cookie 域名
@Value("#{ @environment['shiro.rememberMeManager.cookie.domain'] ?: null }")
protected String rememberMeCookieDomain;
 
// RememberMe Cookie 路径
@Value("#{ @environment['shiro.rememberMeManager.cookie.path'] ?: null }")
protected String rememberMeCookiePath;
 
// RememberMe Cookie Secure
@Value("#{ @environment['shiro.rememberMeManager.cookie.secure'] ?: false }")
protected boolean rememberMeCookieSecure;
 
// RememberMe Cookie SameSite
@Value("#{ @environment['shiro.rememberMeManager.cookie.sameSite'] ?: T(org.apache.shiro.web.servlet.Cookie.SameSiteOptions).LAX }")
protected Cookie.SameSiteOptions rememberMeSameSite;
 
/**
 * 创建本地SessionManager Bean
 */
protected SessionManager nativeSessionManager() {
    // 默认为DefaultWebSessionManager
    DefaultWebSessionManager webSessionManager = new DefaultWebSessionManager();
 
    // 配置SessionManager Bean
    webSessionManager.setSessionIdCookieEnabled(sessionIdCookieEnabled);
    webSessionManager.setSessionIdUrlRewritingEnabled(sessionIdUrlRewritingEnabled);
    webSessionManager.setSessionIdCookie(sessionCookieTemplate());
 
    webSessionManager.setSessionFactory(sessionFactory());
    webSessionManager.setSessionDAO(sessionDAO());
    webSessionManager.setDeleteInvalidSessions(sessionManagerDeleteInvalidSessions);
 
    return webSessionManager;
}
 
/**
 * 创建Session Cookie Bean
 */
protected Cookie sessionCookieTemplate() {
    return buildCookie(
            sessionIdCookieName,
            sessionIdCookieMaxAge,
            sessionIdCookiePath,
            sessionIdCookieDomain,
            sessionIdCookieSecure,
            sessionIdCookieSameSite);
}
 
/**
 * 创建RememberMe Cookie Bean
 */
protected Cookie rememberMeCookieTemplate() {
    return buildCookie(
            rememberMeCookieName,
            rememberMeCookieMaxAge,
            rememberMeCookiePath,
            rememberMeCookieDomain,
            rememberMeCookieSecure,
            rememberMeSameSite);
}
 
/**
 * 创建Cookie Bean
 */
protected Cookie buildCookie(String name, int maxAge, String path, String domain, boolean secure) {
    return buildCookie(name, maxAge, path, domain, secure, Cookie.SameSiteOptions.LAX);
}
 
/**
 * 创建Cookie Bean
 */
protected Cookie buildCookie(String name, int maxAge, String path, String domain, boolean secure, Cookie.SameSiteOptions sameSiteOption) {
    Cookie cookie = new SimpleCookie(name);
    cookie.setHttpOnly(true);
    cookie.setMaxAge(maxAge);
    cookie.setPath(path);
    cookie.setDomain(domain);
    cookie.setSecure(secure);
    cookie.setSameSite(sameSiteOption);
 
    return cookie;
}
 
/**
 * 创建SessionManager Bean
 */
@Override
protected SessionManager sessionManager() {
    if (useNativeSessionManager) {
        return nativeSessionManager();
    }
    return new ServletContainerSessionManager();
}
 
/**
 * 创建RememberMeManager Bean
 */
@Override
protected RememberMeManager rememberMeManager() {
    // 默认为CookieRememberMeManager
    CookieRememberMeManager cookieRememberMeManager = new CookieRememberMeManager();
 
    // 配置RememberMeManager Bean
    cookieRememberMeManager.setCookie(rememberMeCookieTemplate());
    return cookieRememberMeManager;
}
 
/**
 * 创建SubjectFactory Bean
 */
@Override
protected SubjectFactory subjectFactory() {
    // 默认为DefaultWebSubjectFactory
    return new DefaultWebSubjectFactory();
}
 
/**
 * 创建SubjectFactory Bean
 */
@Override
protected SessionStorageEvaluator sessionStorageEvaluator() {
    return new DefaultWebSessionStorageEvaluator();
}
 
/**
 * 创建SessionsSecurityManager Bean
 */
@Override
protected SessionsSecurityManager createSecurityManager() {
    // 默认为DefaultWebSecurityManager
    DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
 
    // 配置SessionsSecurityManager Bean
    securityManager.setSubjectDAO(subjectDAO());
    securityManager.setSubjectFactory(subjectFactory());
    securityManager.setRememberMeManager(rememberMeManager());
 
    return securityManager;
}
 
/**
 * 创建ShiroFilterChainDefinition Bean
 */
protected ShiroFilterChainDefinition shiroFilterChainDefinition() {
    // 默认为DefaultShiroFilterChainDefinition
    DefaultShiroFilterChainDefinition chainDefinition = new DefaultShiroFilterChainDefinition();
 
    // 配置ShiroFilterChainDefinition Bean
    chainDefinition.addPathDefinition("/**", "authc");
    return chainDefinition;
}
 
/**
 * 创建ShiroUrlPathHelper Bean
 */
protected ShiroUrlPathHelper shiroUrlPathHelper() {
    // 默认为ShiroUrlPathHelper
    return new ShiroUrlPathHelper();
}

ShiroWebConfiguration

简介

Shiro 配置器,简单调用父类方法创建Shiro框架Web环境下需要的Bean

核心代码

/**
 * 创建SubjectDAO Bean
 */
@Bean
@Override
protected SubjectDAO subjectDAO() {
    return super.subjectDAO();
}
 
/**
 * 创建SessionStorageEvaluator Bean
 */
@Bean
@Override
protected SessionStorageEvaluator sessionStorageEvaluator() {
    return super.sessionStorageEvaluator();
}
 
/**
 * 创建SessionFactory Bean
 */
@Bean
@Override
protected SessionFactory sessionFactory() {
    return super.sessionFactory();
}
 
/**
 * 创建SessionDAO Bean
 */
@Bean
@Override
protected SessionDAO sessionDAO() {
    return super.sessionDAO();
}
 
/**
 * 创建Session Cookie Bean
 */
@Bean(name = "sessionCookieTemplate")
@Override
protected Cookie sessionCookieTemplate() {
    return super.sessionCookieTemplate();
}
 
/**
 * 创建RememberMe Cookie Bean
 */
@Bean(name = "rememberMeCookieTemplate")
@Override
protected Cookie rememberMeCookieTemplate() {
    return super.rememberMeCookieTemplate();
}
 
/**
 * 创建RememberMeManager Bean
 */
@Bean
@Override
protected RememberMeManager rememberMeManager() {
    return super.rememberMeManager();
}
 
/**
 * 创建SubjectFactory Bean
 */
@Bean
@Override
protected SubjectFactory subjectFactory() {
    return super.subjectFactory();
}
 
/**
 * 创建Authorizer Bean
 */
@Bean
@Override
protected Authorizer authorizer() {
    return super.authorizer();
}
 
/**
 * 创建AuthenticationStrategy Bean
 */
@Bean
@Override
protected AuthenticationStrategy authenticationStrategy() {
    return super.authenticationStrategy();
}
 
/**
 * 创建Authenticator Bean
 */
@Bean
@Override
protected Authenticator authenticator() {
    return super.authenticator();
}
 
/**
 * 创建SessionManager Bean
 */
@Bean
@Override
protected SessionManager sessionManager() {
    return super.sessionManager();
}
 
/**
 * 创建SessionsSecurityManager Bean
 */
@Bean
@Override
protected SessionsSecurityManager securityManager(List<Realm> realms) {
    return super.securityManager(realms);
}
 
/**
 * 创建ShiroFilterChainDefinition Bean
 */
@Bean
@Override
protected ShiroFilterChainDefinition shiroFilterChainDefinition() {
    return super.shiroFilterChainDefinition();
}
 
/**
 * 创建ShiroUrlPathHelper Bean
 */
@Bean
@Override
protected ShiroUrlPathHelper shiroUrlPathHelper() {
    return super.shiroUrlPathHelper();
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值