谷粒学院SpringSecurity认证流程详解

文章详细分析了前端登录时调用接口的流程,包括请求携带token以及请求拦截器的使用。后端部分,重点讲述了SpringSecurity的用户认证流程,包括Authentication接口、UsernamePasswordAuthenticationFilter、AuthenticationManager、AuthenticationProvider、PasswordEncoder和UserDetailsService的角色和工作方式。整个认证过程中,用户信息、权限和密码验证都在安全框架内进行,登录成功后,token信息存储在前端,并用于后续请求的身份验证。

登录功能前端分析

前端会调用此接口去实现登录

// 登录
export function login(username, password) {
   return request({
     url: '/admin/acl/login',
     method: 'post',
     data: {
       username,
       password
     }
   })
 }

request请求会经过request拦截器,给请求携带一个token的字段,token值是从Cookie中获取的,由于现在是登录阶段,所以没有该值。

===========================config/dev.env.js===========================================
module.exports = merge(prodEnv, {
  NODE_ENV: '"development"',
  BASE_API: '"http://localhost:8222"',
})
==========================request.js=====================================
// 创建axios实例
const service = axios.create({
  baseURL: process.env.BASE_API, // api 的 base_url
  timeout: 20000 // 请求超时时间
})

// request拦截器
service.interceptors.request.use(
  config => {
    if (store.getters.token) {
      // 让每个请求携带自定义token
      config.headers['token'] = getToken()
    }
    return config
  },
  error => {
    console.log(error)
    Promise.reject(error)
  }
)
==================auth.js=================================
const TokenKey = 'Admin-Token'

export function getToken() {
  return Cookies.get(TokenKey)
}

export function setToken(token) {
  return Cookies.set(TokenKey, token)
}

export function removeToken() {
  return Cookies.remove(TokenKey)
}

没登录时浏览器存储的cookie值

以下是我成功登录的截图

最终前端的请求路径为 http://localhost:8222/admin/acl/login

登录后端分析

1、网关

包含acl的请求路径会被网关拦截,然后去注册中心找对应的服务名,再转发到对应的权限管理模块中去

spring:
  application:
    name: service-gateway
  cloud:
    #nacos服务地址
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848
    #使用服务发现路由
    gateway:
      discovery:
        locator:
          enabled: true
      routes:
        - id: service-acl
          uri: lb://service-acl
          predicates:
            - Path=/*/acl/**

2、SpringSecurity

以下是SpringSecurity的用户认证流程,下面我会详细分析

  • Authentication接口: 它的实现类,表示当前访问系统的用户,封装了用户相关信息。

  • AuthenticationManager接口:定义了认证Authentication的方法

  • UserDetailsService接口:加载用户特定数据的核心接口。里面定义了一个根据用户名查询用户信息的方法。

  • UserDetails接口:提供核心用户信息。通过UserDetailsService根据用户名获取处理的用户信息要封装成UserDetails对象返回。然后将这些信息封装到Authentication对象中。

2.1用户认证核心组件

我们系统中会有许多用户,确认当前是哪个用户正在使用我们系统就是登录认证的最终目的。这里我们就提取出了一个核心概念:当前登录用户/当前认证用户。整个系统安全都是围绕当前登录用户展开的,这个不难理解,要是当前登录用户都不能确认了,那A下了一个订单,下到了B的账户上这不就乱套了。这一概念在Spring Security中的体现就是 Authentication,它存储了认证信息,代表当前登录用户。

我们在程序中如何获取并使用它呢?我们需要通过 SecurityContext 来获取Authentication,SecurityContext就是我们的上下文对象!这个上下文对象则是交由 SecurityContextHolder 进行管理,你可以在程序任何地方使用它:

Authentication authentication = SecurityContextHolder.getContext().getAuthentication();

SecurityContextHolder原理非常简单,就是使用ThreadLocal来保证一个线程中传递同一个对象!

现在我们已经知道了Spring Security中三个核心组件:

  1. Authentication:存储了认证信息,代表当前登录用户

  1. SeucirtyContext:上下文对象,用来获取Authentication

  1. SecurityContextHolder:上下文管理对象,用来在程序任何地方获取SecurityContext

Authentication中是什么信息?

  1. Principal:用户信息,没有认证时一般是用户名,认证后一般是用户对象

  1. Credentials:用户凭证,一般是密码

  1. Authorities:用户权限

2.2 UsernamePasswordAuthenticationFilter

用户在提交完用户名和密码后,请求会首先来到 UsernamePasswordAuthenticationFilter,执行其 doFilter方法。

这个方法 UsernamePasswordAuthenticationFilter 并没有实现,而是其父类AbstractAuthenticationProcessingFilter 实现的。

流程如下:

评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小鲁蛋儿

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值