您的位置:首页 > 科技 > IT业 > 小程序排名优化_b2b怎么开通_公司以优化为理由裁员合法吗_重庆seo网络优化师

小程序排名优化_b2b怎么开通_公司以优化为理由裁员合法吗_重庆seo网络优化师

2025/1/8 10:43:41 来源:https://blog.csdn.net/weixin_45766875/article/details/144888817  浏览:    关键词:小程序排名优化_b2b怎么开通_公司以优化为理由裁员合法吗_重庆seo网络优化师
小程序排名优化_b2b怎么开通_公司以优化为理由裁员合法吗_重庆seo网络优化师

        大家好我是豆豆,一个具备多年工作经验并且致力于教大家思路的全栈开发程序员,今天为大家带来单点登录的解决方案。提起单点登录不的不提及各个软件架构演变,在此不做详细描述,读者可移步早期原创文章《软件架构的演变过程》。

一、为什么

单点登录是由原先的单体架构的局限性所出现的,具体分析图片如下:

        原先的单体架构,用户登录成功后,会将用户信息存储在session中,以session是否存在用户信息来判断是否存在登录成功,但是随着后来分布式架构的出现,不同的模块部署在不同的服务器上,那么就会出现一个情况,每次访问不同的模块都需要进行登录,给用户造成的体验极差,因此需要一个全局的认证中心的出现,通过认证中心来判断是否登录成功,并去往请求的页面,解决了单体架构的弊端。

二、原理分析

        用户请求一个页面,首先会通过认证中心判断是否需要登录,如果没有登录,则有认证中心重定向到登陆页面,用户输入密码正常的登录,如果登录成功,直接跳转到请求的页面,并将信息生成一个token存储在cookie里面,那么如果下次再次请求有关系的服务器页面是可以通过是否存在cookie来判断是否登录,并跳转对应的请求页面.

三、如何做

1.验证

        根据用户名和密码对用户的信息进行校验,并且生成token,将token和nickname存往前端,将用户登录的id以及ip转换为json对象,存往reids等待认证中心认证.

2.认证

        认证中心使用gateway网关进行过滤,具体思路如下:

        用户登录成功后会在cookie里面存一个token,前端通过拦截将token放在请求头里面,由网关进行过滤拦截重定向,具体的步骤如下:

                ①验证是否为内部资源

                ②获取到用户的userId

根据通过获取token,来拿到redis里面存储的ip和id,对ip进行比对,得出三种结果

""不存在"userid"存在"-1"ip地址不对应,token可能有泄漏的风险

③根据useerId验证token是否泄漏,给出提示

④对特定的路径处理比如 /api//auth/

⑤设置白名单,当userid为空时,根据白名单里面设置的值与请求的路径进行比对,如果有匹配的则重定向对应的页面

⑥..........其余过滤情况

⑦当所有的过滤情况排除后,将userid存储到请求的header里面,并有下一个请求来获取header里面的数据进行操作.

⑧放行

参考代码:

public class AuthGlobalFilter implements GlobalFilter {private AntPathMatcher antPathMatcher=new AntPathMatcher();@Autowiredprivate RedisTemplate redisTemplate;@Value("${authUrls.url}")private String authUrls;/**实现对所有请求的过滤
@param exchange
@param chain
@return
*/@Overridepublic Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {/*实现思路:
①内部接口不允许访问 inner * ②获取userid
是否登录
是否存在token,以及是否被盗用
③api方法过滤("/api/../auth/..")
④白名单(无userId重定向到登录页面)
⑤生成userId存在header里面
*/
//①处理内部接口//获取请求对象ServerHttpRequest request = exchange.getRequest();//获取请求的uriString path = request.getURI().getPath();//创建匹配规则String authUri="//inner/";if (antPathMatcher.match(authUri,path)){//匹配成功,属于内部接口,不让访问//获取回应对象ServerHttpResponse response = exchange.getResponse();//准备返回的数据return out(response, ResultCodeEnum.PERMISSION);}//②获取userId -1(token被盗用) ""(不存在) xxxx(token存在)String userId=this.getUserId(request);//③判断token是否盗用if ("-1".equals(userId)){//被盗用,给出提示ServerHttpResponse response = exchange.getResponse();//准备数据return out(response, ResultCodeEnum.ILLEGAL_REQUEST);}//④判断是否是api方法String apiPath="/api//auth/";if(antPathMatcher.match(apiPath,path)){if (StringUtils.isEmpty(userId)){//匹配成功,属于内部接口,不让访问//获取回应对象ServerHttpResponse response = exchange.getResponse();return out(response, ResultCodeEnum.LOGIN_AUTH);}}//⑤设置白名单,也就意味着白名单里面的所有都拦截给他重定向到登录页面//获取白名单String[] split = authUrls.split(",");if (split!=null&&split.length>0){for (String waite : split) {//遍历每一个白名单比交if (path.indexOf(waite)!=-1&&StringUtils.isEmpty(userId)){//重定向到登录页面ServerHttpResponse response = exchange.getResponse();//设置状态码response.setStatusCode(HttpStatus.SEE_OTHER);//设置参数response.getHeaders().set(HttpHeaders.LOCATION,"http://www.gmall.com/login.html?originUrl="+request.getURI());//重定向return response.setComplete();}} }//⑥排除所有情况后开始将userId放入headers里面,存到下一个后端请求if (!StringUtils.isEmpty(userId)){request.mutate().header("userId",userId).build();return chain.filter(exchange.mutate().request(request).build());}//没有问题,放行return chain.filter(exchange);}private Mono<Void> out(ServerHttpResponse response, ResultCodeEnum loginAuth) {//准备返回的数据Result<Object> build = Result.build(null, loginAuth);//转换为bytebyte[] bytes = JSONObject.toJSONString(build).getBytes(StandardCharsets.UTF_8);DataBuffer wrap = response.bufferFactory().wrap(bytes);//处理返回乱码response.getHeaders().add("Content-Type", "application/json;charset=UTF-8");//返回结果return response.writeWith(Mono.just(wrap));}/**获取用户id
@param request
@return
*/private String getUserId(ServerHttpRequest request) {//①分别从cookie和header里面获取token//定义tokenString token="";//先从请求头里面获取tokenList<String> tokenHeader = request.getHeaders().get("token");if (tokenHeader!=null){//获取单个tokentoken = tokenHeader.get(0);}else {//请求头为空,不存在token.从cookie里面取List<HttpCookie> cookies = request.getCookies().get("token");if (cookies!=null){token = cookies.get(0).getValue();}}//②校验获取userId//准备redis的keyString key=RedisConst.USER_LOGIN_KEY_PREFIX+token;//从redis里面拿到valueString tokenRedis = (String) redisTemplate.opsForValue().get(key);//校验if (!StringUtils.isEmpty(tokenRedis)){//redis存在//获取ip和userIdJSONObject jsonObject = JSONObject.parseObject(tokenRedis);String RedisIp = (String) jsonObject.get("ip");//获取当前的ipString currentIp = IpUtil.getGatwayIpAddress(request);if (!RedisIp.equals(currentIp)){//存储ip与当前ip不对应//token被盗return "-1";}else {//存在String userId = (String) jsonObject.get("userId");return userId;}}//不存在return "";}}​

四、总结:以验证码登录为例

        单点登录主要解决的是原来的单体架构中将信息放到session域中在分布式系统中重复登录的弊端,从流程和后台技术两个方面说起:

流程

        用户请求页面时首先会经过认证中心去判断cookie里面是否存在token,来判断用户是否登录,如果不存在则重定向到登录页面,从数据库进行比对数据库和密码,比对成功后,生成token存在cookie里面,并转发到用户请求的页面,如果下次用户再次请求,只需根据token是否存在到达认证中心进行判断.

后端

A:认证中心:由gateway网关来承担,用户请求发到网关,由网关进行解析,设置白名单过滤等等操作

B:redis验证码的存储

        首先根据手机号判断redis里面是否有验证码,来排除用户重发发送验证码的可能,然后发送验证码并利用redis的失效性,将用户的手机号作为key,验证码作为value存在redis里面

C:登录

        等用户发来登录请求,后台获取到用户的手机号和验证码进行比对,如果不成功则进行注册,如果成功或者注册完成,根据手机号从数据库里面查询用户的信息,获取到用户的id以及昵称,通过jwt工具进行base64编码得到一个token,并将token以及name存到前端的cookie里面,通过cookie里面是否存在token来判断用户是否登录成功,为了解决cookie不能跨域的问题,前端会有一个拦截器,将token存往header里面,这样我们每次请求都会带有header,方便后续的操作.

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com