springcloud实现各个模块的统一登陆逻辑和关键代码

本文介绍了如何在SpringCloud项目中实现统一登录逻辑,主要利用JWT生成token,通过Filter进行登录验证。文章详细阐述了统一登录的含义,并对比了Interceptor与Filter的区别,提出在各模块上使用Filter进行登录校验以满足不同项目的需求。具体实现包括JWT的引入,token生成,登录接口,以及前端携带token进行请求的流程。
摘要由CSDN通过智能技术生成

标题起的有点问题,因为统一登陆不一定实在同一个项目的不同模块,也可以是不同项目的不同模块。既可以是一个大的springcloud项目,也可以是多个分属于不同项目的springboot项目。

1.首先要理解何为统一登陆?

统一登陆可以通过一个具体的app来实现。下面是一张美团app的首页截图。

首页上面的美食,电影演出,酒店住宿,休闲娱乐,外卖五大模块都整合到这个app里。但是要知道美团之前就是美团外卖,后来的这些功能都是整合进来的。分属于不同的独立引用或者app中,肯定有自己独立的登陆。这些应用的不在一个模块甚至项目中。但是整合到美团app后,只要在app这层登陆后,这五大模块的登陆态就变成已登录状态,从而访问里面的信息不会应为再次登陆而被登陆拦截。一次登陆后,在这五个功能模块中都是已经登陆,便是统一登陆!

统一登陆绝不是美团app登陆后,在电脑网页版就也是登录态,这是不可能实现的能力。统一登陆是一种整合能力的表现。

在这里插入图片描述

2.实现统一登陆的技术选择

美团外卖的统一登陆或许有别的实现统一登陆的方式。上面只是以app的首页讲解何为统一登陆。这里的实现是我们公司的具体实现,和美团无关。

实现对请求的拦截处理有两种方式: implements javax.servlet.Filterimplements org.springframework.web.servlet.HandlerInterceptor

HandlerInterceptor在方法的preHandle,postHandle,afterCompletion实现拦截逻辑。Filter是在方法 doFilter()中实现拦截逻辑。

但是这里要有个清楚的认识Spring的Interceptor与Servlet的Filter区别点

Filter作用于servlet容器,Interceptor作用于spring容器。一个请求过来经过二者的先后顺序是这样的。

Filter前处理 --> Interceptor前处理 --> action --> Interceptor后处理 --> Filter后处理
  1. 如果只是单纯的登录校验,将校验的代码放在Filter里面会更好,因为这样请求都不会到Spring里面就已经被Servlet拒绝了,这样可以更加好的保证Spring的安全。
  2. 如果项目需要根据权限去拦截,需要根据用户信息去查询数据库表。这就不可避免的要使用Spring的组件了,这种情况下就使用Interceptor处理好一些。
  3. 但是对于springboot项目,通过对filter注解@Component,即 org.springframework.stereotype.Component来让spring来管理。也是可以在filter中实现注具体service层的。

3.项目中的技术实现思路

对于springcloud项目的统一登陆大都放在zuul网关层实现,对登陆进行校验,拦截。对于zuul下的项目都需要登陆校验的项目来说是没有问题。但是我们的项目的登陆需求并不是都需要。有写还不需要登陆。大致是这样的。项目一,二和订单模块需要登陆,但是三方支付模块和open模块是不需要登陆的。而这些都在zuul网关的治理下。如果在zuul网关加上登陆校验,则不需要登陆的模块就会请求拦截,显示未登录进不了服务模块。
所以我们采用在各自模块上通过filter实现各自的登陆校验。而登陆要满足各个项目实现统一登陆。
在这里插入图片描述

技术实现简单说就是:jwt实现token回传给客户端,客户端的每次请求都带着token给后台。token+filter实现登陆态校验。token+session实现一次解析用户信息,项目层面更简单获取用户信息。

4.技术的具体实现

用户注册登陆接口(filter放行)返回生成的token,而后所有请求会被filter拦截进行token校验。

  • 4.1 引入jwt的pom依赖
        <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt</artifactId>
            <version>0.9.1</version>
        </dependency>
  • 4.2 通过jwt生成token的工具类
public class Constant {
   
	public static final String TOKEN               = "token";
	public static final String EXPIRE_TIME               = "expireTime";
	public static final String USER_ID = "userId";
	public static final String LOGIN_NAME = "loginName";
	public static final String USER_NAME = "userName";
	public static final String MOBILE = "mobile";
	public static final String IP_ADDRESS = "ipAddress";
}



import com.server.constant.Constant;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtException;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

@SuppressWarnings("Duplicates")
@Component
public class TokenComponent {
   

    private             Logger log                =LoggerFactory.getLogger(TokenComponent.class);
    public static final String CLAIM_KEY_USER     = "userId";
    public static final String CLAIM_KEY_CREATED  = "created";
    public static final String CLAIM_KEY_MOBILE   = "mobile";
    public static final String CLAIM_KEY_USERNAME = "userName";
    public static final String CLAIM_KEY_LOGINNAME = "loginName";

    private String secret = "secret";

    /**
     * 7 days
     */
    private Long defaultExpiration = 604800L;

    /**
     * 生成token
     * @param mobile 手机
     * @param userId 用户ID
     * @param userName 用户名称
     * @param expiration 过期时间
     * @return TOKEN
     */
    public Map<String, String> generateToken(String userId, String mobile, String userName,String loginName, Long expiration) {
   
        Map<String, Object> claims = new HashMap<>(5);
        claims.put(CLAIM_KEY_USER, userId);
        claims.put(CLAIM_KEY_MOBILE, mobile);
        claims.put(CLAIM_KEY_CREATED, new Date());
        claims.put(CLAIM_KEY_USERNAME, userName);
        claims.put(CLAIM_KEY_LOGINNAME, loginName);
        Date expirationDate;
        if (expiration == null) {
   
            expirationDate = new Date(System.currentTimeMillis() + defaultExpiration * 1000
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

万米高空

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

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

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

打赏作者

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

抵扣说明:

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

余额充值