现在的电商系统,一般我们除了登录和退出及其他无关紧要的接口之外,其他的接口请求的时候我们一般都会涉及到对接口进行用户鉴权,如果用户未登录,则不给用户展示相关的页面,并且前端会跳转到用户登录页面。这样做一般有2个大的用处:
1、通过提取用户信息及用户访问信息,进而分析用户的偏好,做千人千面的推荐广告。 2、通过提取用户信息及用户访问信息,做风控,避免第三方暴力破解或者爬虫等方式获取数据。
所以这里的话我们提到这两个点。对于前面我们的这个演示项目,我们已经添加了spring cloud gateway网关了,因此这里的话我们就在网关层面做出针对于除用户登录之外的接口做用户鉴权的操作。这里的鉴权比较简单,只需要在spring cloud gateway网关里面添加一个鉴权的filter就可以了,具体的示例代码如下:
package org.gateway.service.filter;
import java.util.List;
import org.apache.commons.lang.StringUtils;
import org.common.manager.redis.RedisManagaer;
import org.common.model.constants.RedisPrefix;
import org.common.model.http.BaseResponse;
import org.common.model.http.HttpStatusCode;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.MediaType;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
/**
* 鉴权过滤器 验证token
*/
@Component
@Slf4j
public class AuthorizeFilter implements GlobalFilter, Ordered {
private static final String AUTHORIZE_TOKEN = "token";
@Value("${auth.whitelist.url}")
private List<String> urls;
@Autowired
private RedisManagaer redisManagaer;
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
// 1. 获取请求
ServerHttpRequest request = exchange.getRequest();
// 2. 则获取响应
ServerHttpResponse response = exchange.getResponse();
// 3. 如果是登录请求则放行
if (urls.contains(request.getURI().getPath())) {
return chain.filter(exchange);
}
// 4. 请求头中获取令牌
String token = request.getHeaders().getFirst(AUTHORIZE_TOKEN);
// 5. 判断请求头中是否有令牌
if (StringUtils.isEmpty(token)) {
return this.userNotLoginAction(response);
}
try {
String userNos = (String) redisManagaer.getHashValue(RedisPrefix.USERTOKEN + token);
if(StringUtils.isBlank(userNos)) {
return this.userNotLoginAction(response);
}
ServerHttpRequest newRequest = exchange.getRequest().mutate()
.header("userNo", userNos).build();
return chain.filter(exchange.mutate().request(newRequest).build());
} catch (Exception e) {
log.error(e.getMessage(), e);
return this.userNotLoginAction(response);
}
}
private Mono<Void> userNotLoginAction(ServerHttpResponse response) {
BaseResponse resultJson = BaseResponse.fail(HttpStatusCode.USERNOTLOGIN);
byte[] bytes = JSONObject.toJSONBytes(resultJson);
response.getHeaders().add("Content-Type", MediaType.APPLICATION_JSON_VALUE);
DataBuffer buffer = response.bufferFactory().wrap(bytes);
return response.writeWith(Flux.just(buffer));
}
@Override
public int getOrder() {
return 0;
}
}这里我们的url白名单通过配置文件进行配置即可,这里我们在application.yml文件中进行配置:
此时除了login接口不会做鉴权校验之外,其他的接口等会做鉴权校验,如果用户未登录,则跳转到用户登录界面上。
备注:
1、这里我们在源码里面,主要是在gateway里面添加了用户鉴权的filter。
2、在源码中我们引入了jetcache缓存,主要做一个范例使用。
最后按照惯例,附上本案例的源码,登陆后即可下载。










还没有评论,来说两句吧...