ASP.NET Core 问答 03:认证、授权、安全、缓存与状态
041 认证与授权有什么区别?
难度: 基础
查看参考答案
结论: 认证确定调用者是谁,授权判断该身份能否执行操作
原因: 两者是先建立身份再评估策略的不同阶段
边界: 匿名端点可跳过授权要求,但不能把未验证输入当可信身份
最小示例: JWT 验签后再检查 scope 策略
042 为什么应用可能需要多个认证方案?
难度: 基础
查看参考答案
结论: 不同端点或客户端可能使用 Cookie、Bearer 或外部登录等不同凭据
原因: 方案定义处理挑战、认证和禁止访问的具体处理器
边界: 必须明确默认方案或在策略中指定方案,避免错误处理器响应
最小示例: 网页用 Cookie,API 用 Bearer
043 Cookie 认证的票据存在哪里?
难度: 基础
查看参考答案
结论: 认证票据经 Data Protection 保护后通常存入 Cookie,或仅存会话标识并使用服务端票据存储
原因: 票据大小、撤销、密钥共享和 Cookie 属性都会影响行为
边界: Cookie 加密不等于可随意包含敏感业务数据
最小示例: 集群节点共享 Data Protection 密钥环
044 JWT Bearer 验证必须检查什么?
难度: 基础
查看参考答案
结论: 至少验证签名、发行者、受众和生命周期,并按需要限制算法与时钟偏差
原因: 只解码 Base64 无法证明令牌可信
边界: 密钥轮换和元数据获取失败需要缓存与监控策略
最小示例: 不要信任未验证 token 中的 role
045 401 与 403 应如何区分?
难度: 基础
查看参考答案
结论: 401 表示未建立可接受身份,403 表示已认证但无权限
原因: 客户端可据此决定重新认证还是提示无权
边界: 为隐藏资源存在性可按威胁模型调整外部响应,但日志仍应保留原因
最小示例: 缺 token 返回 401,权限不足返回 403
046 基于策略的授权包含哪些元素?
难度: 基础
查看参考答案
结论: 策略由 Requirement 组成,Handler 根据用户和资源评估要求
原因: 它把授权规则从控制器分支中抽离并可组合测试
边界: Handler 不应自行信任客户端传来的角色头
最小示例: RequireClaim 与自定义年龄要求
047 资源授权何时必要?
难度: 进阶
查看参考答案
结论: 权限依赖具体订单、文档或租户实例时,需要把资源传给授权服务
原因: 仅靠路由上的静态角色无法判断对象所有权
边界: 必须先安全加载资源,并防止通过 ID 猜测越权
最小示例: AuthorizeAsync(User, order, “CanEdit”)
048 Claims、Roles 和 Permissions 如何取舍?
难度: 进阶
查看参考答案
结论: Claim 是身份声明,Role 是常见分组,Permission 或策略表达更细粒度能力
原因: 大型系统直接把所有业务规则硬编码为角色会膨胀
边界: 声明仍需由可信发行者产生并考虑撤销与更新延迟
最小示例: 策略要求 permission=orders.write
049 ASP.NET Core Identity 解决什么问题?
难度: 进阶
查看参考答案
结论: 它提供用户、密码哈希、令牌、登录和角色等账户基础设施
原因: 它不是完整业务授权模型,也不自动解决多租户资源权限
边界: 可替换存储和 UI,但安全参数变更要评估迁移
最小示例: Identity 管账号,策略管订单权限
050 Data Protection 的 key ring 为什么必须持久化?
难度: 进阶
查看参考答案
结论: 它让 Cookie、临时数据等受保护载荷跨重启和节点继续解密
原因: 临时本地密钥会导致重启登出,多节点独立密钥会随机失败
边界: 共享位置还必须限制访问并考虑静态加密和轮换
最小示例: 容器挂载受保护的共享密钥目录
051 CORS 是什么安全边界?
难度: 进阶
查看参考答案
结论: 它是浏览器对跨源脚本读取响应的限制,不是服务器访问控制
原因: 非浏览器客户端不受 CORS 约束,端点仍要认证授权
边界: AllowAnyOrigin 与凭据不能随意组合,来源列表要精确
最小示例: curl 可绕过浏览器 CORS
052 为什么 Cookie 场景需要防 CSRF?
难度: 进阶
查看参考答案
结论: 浏览器会自动附带目标站点 Cookie,攻击站点可诱导用户发送有副作用请求
原因: 防伪令牌、SameSite 和正确 HTTP 方法共同降低风险
边界: Bearer 放在自定义 Authorization 头且攻击者不可读时风险模型不同
最小示例: 表单 POST 验证 antiforgery token
053 如何降低 XSS 风险?
难度: 进阶
查看参考答案
结论: 默认编码不可信输出、避免拼接 HTML,并使用 CSP 等纵深防御
原因: XSS 可窃取页面数据并以用户身份发请求
边界: 输入过滤不能替代按输出上下文编码,富文本需专用清洗
最小示例: Razor 默认编码普通表达式
054 HSTS 与 HTTPS 重定向有何区别?
难度: 进阶
查看参考答案
结论: 重定向把当前 HTTP 请求转到 HTTPS,HSTS 告诉浏览器后续只用 HTTPS
原因: 首次访问和非浏览器客户端仍有边界,代理终止 TLS 时要正确识别原始协议
边界: 开发环境通常不启用 HSTS,以免影响本地域名
最小示例: 生产发送 Strict-Transport-Security
055 限流策略应按什么维度划分?
难度: 实战
查看参考答案
结论: 按用户、API key、IP、租户或资源成本选择分区键和算法
原因: 只按进程全局计数可能让一个调用者耗尽所有配额
边界: 多实例若需全局额度要使用可协调方案,内置本地计数不能替代业务幂等
最小示例: 登录按账号与 IP 组合限流
056 内存缓存与分布式缓存如何选择?
难度: 实战
查看参考答案
结论: 单实例短期数据可用内存缓存,多实例共享状态通常用分布式缓存
原因: 内存缓存速度快但节点间不一致且重启丢失
边界: 缓存不是事实来源,失效、穿透和序列化都要设计
最小示例: 商品详情缓存以数据库为来源
057 输出缓存与响应缓存有什么区别?
难度: 实战
查看参考答案
结论: 输出缓存由服务器策略决定是否复用响应,响应缓存遵循 HTTP 缓存语义和客户端头
原因: 输出缓存更适合受控服务端缓存,响应缓存强调协议规则
边界: 含用户私有数据的响应不能按公共键共享
最小示例: 按路由值和查询参数变化缓存公开列表
058 如何防止缓存击穿?
难度: 实战
查看参考答案
结论: 对热点 miss 使用请求合并、短锁、提前刷新或过期抖动
原因: 大量并发同时回源会压垮数据库,即使缓存很快也无济于事
边界: 锁的范围和失败恢复必须受控,不能让单节点锁冒充跨节点协调
最小示例: 同一商品键只允许一个加载任务
059 Session 为什么不适合保存关键业务状态?
难度: 实战
查看参考答案
结论: Session 是临时会话数据,可能过期、丢失并依赖客户端标识
原因: 关键订单和权限必须持久化到可靠存储并有事务约束
边界: 多节点 Session 还需分布式存储和一致的数据保护配置
最小示例: 购物车可临时放 Session,支付记录必须入库
060 Cookie 应设置哪些重要属性?
难度: 实战
查看参考答案
结论: 按用途设置 Secure、HttpOnly、SameSite、Path、Domain 和过期策略
原因: 这些属性分别限制传输、脚本访问和跨站携带范围
边界: SameSite=None 通常要求 Secure,范围过宽会扩大泄露面
最小示例: 认证 Cookie 使用 Secure 与 HttpOnly