SpringCloud 微服务用户登录设计

1. 前言

微服务下架构下,借助JWT和Spring Gateway过滤器进行统一用户认证,并通过拦截器解析用户携带Token获取当前用户信息存储到ThreadLocal方便业务模块使用
用户登录时序图

2. 服务架构

主要包含四个模块,使用Nacos作为注册和配置中心

服务类型端口描述
jtool-gatewaygateway8080网关,用作接口转发和认证
jtool-securityauthentication8083用户认证
jtool-templateservice8081业务模块1
jtool-demoservice8082业务模块2

3. 网关过滤器

处于白名单中的接口不需要认证,直接转发(比如/login接口,网关会转发到security模块),非白名单接口需要解析request携带的token,若token合法,将解析token获取的用户名放到request中转发到指定接口即可

@Component
@Import(IgnoreUrlsConfig.class)
public class AuthenticationFilter implements GlobalFilter, Ordered {

    @Autowired
    private IgnoreUrlsConfig ignoreUrlsConfig;

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        ServerHttpRequest request = exchange.getRequest();

        if (ignoreUrlsConfig.getUrls().stream().anyMatch(e ->
                request.getPath().pathWithinApplication().value().equals(e)
        )) {
            return chain.filter(exchange);
        }

        //校验token
        List<String> token = request.getHeaders().get(SecurityConst.TOKEN);
        AssertUtil.isNotEmpty(token, "非法访问");
        try {
            String userName = JwtUtil.getUserName(token.get(0));
            request.mutate().header(SecurityConst.USERNAME,userName);
        }catch (Exception e){
            throw new RuntimeException(e.getMessage());
        }

        return chain.filter(exchange);
    }

    @Override
    public int getOrder() {
        return 0;
    }
}

网关配置文件

server:
  port: 8080
spring:
  main:
    web-application-type: reactive
  application:
    name: jtool-gateway
  cloud:
    nacos:
      server-addr: 127.0.0.1:8848
      username: nacos
      password: nacos
    gateway:
      default-filters:
        - PrintAny
      routes:
        - id: jtool-template-service
          uri: lb://jtool-template-service
          predicates:
            - Path=/test/**,/code/**
        - id: jtool-demo-service
          uri: lb://jtool-demo-service
          predicates:
            - Path=/demo/**
        - id: jtool-security
          uri: lb://jtool-security
          predicates:
            - Path=/login
security:
  whitelist:
    urls:
      - /login

4. 用户认证

认证模块仅仅有个/login接口,比较用户名和密码是否一致即可

@RestController
public class UserController {

    @Autowired
    private UserService userService;

    @RequestMapping("/login")
    public Result<Map<String, String>> login(@RequestBody Map<String, String> userInfo) {
        String username = userInfo.get(SecurityConst.USERNAME);
        userService.authenticate(username, userInfo.get(SecurityConst.PASSWORD));
        String jwt = JwtUtil.createJWT(username);
        return Result.success(Map.of(SecurityConst.TOKEN, jwt));
    }
}

配置文件

spring:
  profiles:
    active: dev
  application:
    name: jtool-security
  cloud:
    nacos:
      username: nacos
      password: nacos
      discovery:
        server-addr: 127.0.0.1:8848
      config:
        #避免没有加载bootstrap导致的错误
        import-check:
          enabled: false
        server-addr: 127.0.0.1:8848


server:
  port: 8083


#mybatis-plus
mybatis-plus:
  mapperLocations: classpath*:mapper/*.xml


5. Token拦截器

业务模块通过拦截器获取网关过滤器设置的用户名,并存储到ThreadLocal中,拦截器在接口结束后会将用户信息从ThreadLocal中移除,避免Memory Leak

/**
 * 将用户信息保存到ThreadLocal上下文中
 */

public class TokenInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        String header = request.getHeader(SecurityConst.USERNAME);
        if (StringUtils.hasText(header)) {
            UserContextHolder.set(SecurityConst.USERNAME, header);
        }
        return HandlerInterceptor.super.preHandle(request, response, handler);
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        UserContextHolder.clear();
    }
}

ThreadLocal代码

package com.cll.common.security.context;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class UserContextHolder {


    private static ThreadLocal<Map<String, Object>> userThreadLocal = new ThreadLocal<>();

    private static void initialize() {
        if (userThreadLocal.get() == null) {
            synchronized (userThreadLocal) {
                if (userThreadLocal.get() == null) {
                    userThreadLocal.set(new ConcurrentHashMap<>());
                }
            }
        }
    }

    public static Object get(String key) {
        initialize();
        return userThreadLocal.get().get(key);
    }

    public static void set(String key, String value) {
        initialize();
        userThreadLocal.get().put(key, value);
    }

    public static void clear() {
        Map<String, Object> stringObjectMap = userThreadLocal.get();
        if (stringObjectMap != null) {
            stringObjectMap.clear();
        }
    }
}

配置文件

server:
  port: 8081
spring:
  profiles:
    active: dev
  application:
    name: jtool-template-service
  cloud:
    nacos:
      username: nacos
      password: nacos
      discovery:
        server-addr: 127.0.0.1:8848
      config:
        import-check:
          enabled: false
        server-addr: 127.0.0.1:8848
security:
    whitelist:
      - /test/user/login


#mybatis-plus
mybatis:
  mapper-locations: classpath*:mapper/*.xml

6. 源代码

https://gitee.com/doc4j/jtool.git
参考ruoyi-cloud

  • 4
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: 2019年黑马项目-畅购商城springcloud微服务实战是一门以实战为主的课程,旨在通过项目实践的方式,帮助学员深入理解和掌握SpringCloud微服务架构以及相关技术的应用。 课程的主要内容包括搭建基础的微服务架构、使用SpringCloud构建服务注册与发现、实现服务间的负载均衡、实现分布式配置中心、服务间的调用与容错处理、使用网关统一接入服务等。通过这些实战练习,学员不仅能够熟悉SpringCloud架构与组件,还能够了解微服务架构下的常见问题与解决方案。 畅购商城项目是一个典型的电商应用,通过实现该项目,学员可以接触到真实的业务场景与需求,并能够将所学知识应用到实际项目中。课程中通过模块化的方式逐步完善商城的功能,包括用户注册登录、商品浏览、购物车管理、订单生成与支付等。通过这些实践,学员除了掌握SpringCloud微服务的开发技术,还能够了解和掌握电商项目的开发流程和注意事项。 该课程的目标是让学员通过实战项目,全面了解和掌握SpringCloud微服务架构的设计与开发,在此基础上能够独立完成具有较高要求的微服务项目。通过参与实战项目的过程,学员还能够提升团队协作能力、解决问题的能力以及项目管理能力。 通过这门课程的学习,学员将会对SpringCloud微服务架构有更深入的理解,并能够将这些知识应用到实际项目中,提高自己在微服务开发领域的竞争力。 ### 回答2: 2019年黑马项目-畅购商城springcloud微服务实战是一个基于springcloud微服务架构的商城项目。该项目的目标是通过运用微服务的理念和技术,构建一个高可用、可扩展的商城系统。 在该项目中,使用了springcloud的多个组件,如Eureka注册中心、Feign负载均衡、Ribbon客户端负载均衡、Hystrix服务降级和容错、Zuul网关等。这些组件共同协作,实现了系统的弹性伸缩和高可用性。 畅购商城的功能包括商品展示、购物车、订单管理、支付、用户管理等。通过将这些功能拆分成独立的微服务,使得系统更加灵活和可维护。同时,使用分布式事务和消息队列来保障数据的一致性和可靠性。 在项目的开发过程中,采用了敏捷开发的方法,以迭代的方式进行开发和测试。通过使用Jenkins进行持续集成和部署,保证了代码的质量和系统的稳定性。 在项目的实战过程中,面临了许多挑战和困难,如微服务之间的通信、服务的负载均衡、服务的容错等。但通过团队的共同努力和不断的学习,最终成功地完成了该项目的开发和部署。 在该项目的实施过程中,不仅学到了springcloud微服务架构的相关知识和技术,还体会到了团队合作和解决问题的能力。该项目的成功实施,不仅为公司带来了商业价值,也提升了团队的技术水平和项目管理能力。 ### 回答3: 2019年黑马项目-畅购商城springcloud微服务实战是一个以Spring Cloud为基础的微服务项目。微服务架构是一种将应用拆分成多个小型服务的架构模式,这些服务可以独立开发、部署、扩展和管理。 畅购商城项目使用了Spring Cloud的一系列子项目,如Eureka、Ribbon、Feign、Hystrix、Zuul等,来实现各个微服务之间的通信、负载均衡、服务降级与熔断等功能。 在项目中,我们会通过Eureka来实现服务的注册与发现,每个微服务都会向Eureka注册自己的地址,其他微服务可以通过Eureka来发现并调用这些服务。而Ribbon则负责实现客户端的负载均衡,可以轮询、随机、加权等方式分发请求。 Feign是一种声明式的HTTP客户端,它简化了服务间的调用方式。我们只需编写接口,并通过注解来描述需要调用的服务和方法,Feign会自动实现远程调用。 Hystrix是一个容错机制的实现,可以通过断路器来实现服务的降级与熔断,当某个服务出现故障或超时时,Hystrix会快速响应并返回一个可控制的结果,从而保证系统的稳定性。 另外,Zuul作为微服务网关,可以实现请求的统一入口和路由转发,提高系统的安全性和性能。 通过这些Spring Cloud的组件,畅购商城项目可以实现高可用、容错、自动扩展等优质的微服务架构。 总之,2019年黑马项目-畅购商城springcloud微服务实战是一个基于Spring Cloud微服务项目,通过使用Spring Cloud的各个子项目,可以实现微服务之间的通信、负载均衡、服务降级与熔断等功能,为项目的开发、部署和管理提供了便利。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值