前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Pig4Cloud之检验token

Pig4Cloud之检验token

原创
作者头像
一觉睡到小时候
发布2022-12-07 14:11:09
5020
发布2022-12-07 14:11:09
举报
文章被收录于专栏:国产程序员国产程序员

## 前端校验请求

/src/page/index/index.vue

```

refreshToken() {

this.refreshTime = setInterval(() => {

checkToken(this.refreshLock, this.$store)

}, 10000)

}

```

`checkToken`

```

/**

* 校验令牌,若有效期小于半小时自动续期

*

* 定时任务请求后端接口返回实际的有效时间,不进行本地计算避免 客户端和服务器机器时钟不一致

* @param refreshLock

*/

export const checkToken = (refreshLock, $store) => {

const token = store.getters.access_token

// 获取当前选中的 basic 认证信息

let basicAuth = getStore({name: 'basicAuth'})

if(validatenull(token) || validatenull(basicAuth)){

return;

}

request({

url: '/auth/token/check_token',

headers: {

isToken: false,

Authorization: basicAuth

},

method: 'get',

params: {token}

}).then(response => {

const expire = response && response.data && response.data.exp

if (expire) {

const expiredPeriod = expire * 1000 - new Date().getTime()

console.log('当前token过期时间', expiredPeriod, '毫秒')

//小于半小时自动续约

if (expiredPeriod <= website.remainingTime) {

if (!refreshLock) {

refreshLock = true

$store.dispatch('RefreshToken')

.catch(() => {

clearInterval(this.refreshTime)

})

refreshLock = false

}

}

}

}).catch(error => {

console.error(error)

})

}

```

## 流程

>当用户携带token 请求资源服务器的资源时,Spring Security 拦截token,进行token 和 userdetails 匹配过程,把无状态的token 转化成具体用户

![image](https://img2022.cnblogs.com/blog/1901531/202211/1901531-20221124150952640-1953156075.png)

## BearerTokenAuthenticationFilter

https://docs.spring.io/spring-security/site/docs/current/api/org/springframework/security/oauth2/server/resource/web/BearerTokenAuthenticationFilter.html

作为一个`OncePerRequestFilter`核心逻辑在`doFilterInternal`中。

```

@Override

protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)

throws ServletException, IOException {

String token;

try {

token = this.bearerTokenResolver.resolve(request);

}

catch (OAuth2AuthenticationException invalid) {

this.logger.trace("Sending to authentication entry point since failed to resolve bearer token", invalid);

this.authenticationEntryPoint.commence(request, response, invalid);

return;

}

if (token == null) {

this.logger.trace("Did not process request since did not find bearer token");

filterChain.doFilter(request, response);

return;

}

BearerTokenAuthenticationToken authenticationRequest = new BearerTokenAuthenticationToken(token);

authenticationRequest.setDetails(this.authenticationDetailsSource.buildDetails(request));

try {

AuthenticationManager authenticationManager = this.authenticationManagerResolver.resolve(request);

Authentication authenticationResult = authenticationManager.authenticate(authenticationRequest);

SecurityContext context = SecurityContextHolder.createEmptyContext();

context.setAuthentication(authenticationResult);

SecurityContextHolder.setContext(context);

this.securityContextRepository.saveContext(context, request, response);

if (this.logger.isDebugEnabled()) {

this.logger.debug(LogMessage.format("Set SecurityContextHolder to %s", authenticationResult));

}

filterChain.doFilter(request, response);

}

catch (AuthenticationException failed) {

SecurityContextHolder.clearContext();

this.logger.trace("Failed to process authentication request", failed);

this.authenticationFailureHandler.onAuthenticationFailure(request, response, failed);

}

}

```

### 1.拦截请求进行鉴权

`BearerTokenAuthenticationFilter` 拦截所有资源服务器的请求。

解析 header 或者参数中的 access_token 字段

![image](https://img2022.cnblogs.com/blog/1901531/202211/1901531-20221124143131405-1773364520.png)

根据access_token 构造出来 `BearerTokenAuthenticationToken `认证对象

![image](https://img2022.cnblogs.com/blog/1901531/202211/1901531-20221124143305690-1170185900.png)

请求`authenticationManager.authenticate(authenticationRequest);`进行鉴权。

![image](https://img2022.cnblogs.com/blog/1901531/202211/1901531-20221124144022298-952097594.png)

### 2.鉴权操作

`BearerTokenAuthenticationFilter`解析 Authentication: Bearer {token} 中的token,交给 `OpaqueTokenAuthenticationProvider`

```

@Override

public Authentication authenticate(Authentication authentication) throws AuthenticationException {

if (!(authentication instanceof BearerTokenAuthenticationToken)) {

return null;

}

BearerTokenAuthenticationToken bearer = (BearerTokenAuthenticationToken) authentication;

OAuth2AuthenticatedPrincipal principal = getOAuth2AuthenticatedPrincipal(bearer);

AbstractAuthenticationToken result = convert(principal, bearer.getToken());

result.setDetails(bearer.getDetails());

this.logger.debug("Authenticated token");

return result;

}

private OAuth2AuthenticatedPrincipal getOAuth2AuthenticatedPrincipal(BearerTokenAuthenticationToken bearer) {

try {

return this.introspector.introspect(bearer.getToken());

}

catch (BadOpaqueTokenException failed) {

this.logger.debug("Failed to authenticate since token was invalid");

throw new InvalidBearerTokenException(failed.getMessage(), failed);

}

catch (OAuth2IntrospectionException failed) {

throw new AuthenticationServiceException(failed.getMessage(), failed);

}

}

```

`OpaqueTokenAuthenticationProvider` 委托 `OpaqueTokenIntrospector `的 `introspect` 去校验 token。

`PigRedisOAuth2AuthorizationService` 通过token value 查询 认证中心下发令牌时 存储的用户认证信息.

![image](https://img2022.cnblogs.com/blog/1901531/202211/1901531-20221124145326378-1962013974.png)

调用`RedisOAuth2AuthorizationService`的`findByToken`

```

@Override

@Nullable

public OAuth2Authorization findByToken(String token, @Nullable OAuth2TokenType tokenType) {

Assert.hasText(token, "token cannot be empty");

Assert.notNull(tokenType, "tokenType cannot be empty");

redisTemplate.setValueSerializer(RedisSerializer.java());

return (OAuth2Authorization) redisTemplate.opsForValue().get(buildKey(tokenType.getValue(), token));

}

```

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
日志服务
日志服务(Cloud Log Service,CLS)是腾讯云提供的一站式日志服务平台,提供了从日志采集、日志存储到日志检索,图表分析、监控告警、日志投递等多项服务,协助用户通过日志来解决业务运维、服务监控、日志审计等场景问题。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档