瀏覽代碼

feat:【IoT 物联网】增加网关 HTTP 协议的鉴权,基于 JWT 轻量级(已测试)

YunaiV 5 月之前
父節點
當前提交
a0a26c3d64

+ 1 - 1
yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/handler/GlobalExceptionHandler.java

@@ -179,7 +179,7 @@ public class GlobalExceptionHandler {
         if(ex.getCause() instanceof InvalidFormatException) {
             InvalidFormatException invalidFormatException = (InvalidFormatException) ex.getCause();
             return CommonResult.error(BAD_REQUEST.getCode(), String.format("请求参数类型错误:%s", invalidFormatException.getValue()));
-        }else {
+        } else {
             return defaultExceptionHandler(ServletUtils.getRequest(), ex);
         }
     }

+ 2 - 1
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/api/device/IoTDeviceApiImpl.java

@@ -10,6 +10,7 @@ import jakarta.annotation.security.PermitAll;
 import org.springframework.context.annotation.Primary;
 import org.springframework.validation.annotation.Validated;
 import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
 import org.springframework.web.bind.annotation.RestController;
 
 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
@@ -30,7 +31,7 @@ public class IoTDeviceApiImpl implements IotDeviceCommonApi {
     @Override
     @PostMapping(RpcConstants.RPC_API_PREFIX + "/iot/device/auth")
     @PermitAll
-    public CommonResult<Boolean> authDevice(IotDeviceAuthReqDTO authReqDTO) {
+    public CommonResult<Boolean> authDevice(@RequestBody IotDeviceAuthReqDTO authReqDTO) {
         return success(deviceService.authDevice(authReqDTO));
     }
 

+ 1 - 1
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDeviceService.java

@@ -235,6 +235,6 @@ public interface IotDeviceService {
      * @param authReqDTO 认证信息
      * @return 是否认证成功
      */
-    boolean authDevice(IotDeviceAuthReqDTO authReqDTO);
+    boolean authDevice(@Valid IotDeviceAuthReqDTO authReqDTO);
 
 }

+ 11 - 6
yudao-module-iot/yudao-module-iot-gateway/src/main/java/cn/iocoder/yudao/module/iot/gateway/protocol/http/router/IotHttpAuthHandler.java

@@ -2,11 +2,13 @@ package cn.iocoder.yudao.module.iot.gateway.protocol.http.router;
 
 import cn.hutool.core.lang.Assert;
 import cn.hutool.core.map.MapUtil;
+import cn.hutool.core.util.BooleanUtil;
 import cn.hutool.core.util.StrUtil;
 import cn.hutool.extra.spring.SpringUtil;
 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
 import cn.iocoder.yudao.module.iot.core.biz.IotDeviceCommonApi;
 import cn.iocoder.yudao.module.iot.core.biz.dto.IotDeviceAuthReqDTO;
+import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage;
 import cn.iocoder.yudao.module.iot.core.mq.producer.IotDeviceMessageProducer;
 import cn.iocoder.yudao.module.iot.core.util.IotDeviceAuthUtils;
 import cn.iocoder.yudao.module.iot.gateway.protocol.http.IotHttpUpstreamProtocol;
@@ -47,7 +49,7 @@ public class IotHttpAuthHandler extends IotHttpAbstractHandler {
 
     @Override
     public CommonResult<Object> handle0(RoutingContext context) {
-        // 解析参数
+        // 1. 解析参数
         JsonObject body = context.body().asJsonObject();
         String clientId = body.getString("clientId");
         if (StrUtil.isEmpty(clientId)) {
@@ -62,20 +64,23 @@ public class IotHttpAuthHandler extends IotHttpAbstractHandler {
             throw invalidParamException("password 不能为空");
         }
 
-        // 执行认证
+        // 2.1 执行认证
         CommonResult<Boolean> result = deviceClientService.authDevice(new IotDeviceAuthReqDTO()
                 .setClientId(clientId).setUsername(username).setPassword(password));
-        if (result == null || !result.isSuccess()) {
+        result.checkError();;
+        if (!BooleanUtil.isTrue(result.getData())) {
             throw exception(DEVICE_AUTH_FAIL);
         }
-
-        // 生成 Token
+        // 2.2 生成 Token
         IotDeviceAuthUtils.DeviceInfo deviceInfo = deviceTokenService.parseUsername(username);
         Assert.notNull(deviceInfo, "设备信息不能为空");
         String token = deviceTokenService.createToken(deviceInfo.getProductKey(), deviceInfo.getDeviceName());
         Assert.notBlank(token, "生成 token 不能为空位");
 
-        // TODO @芋艿:发送上线消息;
+        // 3. 执行上线
+        deviceMessageProducer.sendDeviceMessage(IotDeviceMessage.of(deviceInfo.getProductKey(), deviceInfo.getDeviceName(),
+                        protocol.getServerId())
+                .ofStateOnline());
 
         // 构建响应数据
         return success(MapUtil.of("token", token));

+ 4 - 2
yudao-module-iot/yudao-module-iot-gateway/src/main/java/cn/iocoder/yudao/module/iot/gateway/service/device/IotDeviceClientServiceImpl.java

@@ -1,5 +1,6 @@
 package cn.iocoder.yudao.module.iot.gateway.service.device;
 
+import cn.hutool.core.lang.Assert;
 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
 import cn.iocoder.yudao.module.iot.core.biz.IotDeviceCommonApi;
 import cn.iocoder.yudao.module.iot.core.biz.dto.IotDeviceAuthReqDTO;
@@ -31,7 +32,7 @@ public class IotDeviceClientServiceImpl implements IotDeviceCommonApi {
     public void init() {
         IotGatewayProperties.RpcProperties rpc = gatewayProperties.getRpc();
         restTemplate = new RestTemplateBuilder()
-                .rootUri(rpc.getUrl() + "/rpc-api/iot/device/")
+                .rootUri(rpc.getUrl() + "/rpc-api/iot/device")
                 .readTimeout(rpc.getReadTimeout())
                 .connectTimeout(rpc.getConnectTimeout())
                 .build();
@@ -39,7 +40,7 @@ public class IotDeviceClientServiceImpl implements IotDeviceCommonApi {
 
     @Override
     public CommonResult<Boolean> authDevice(IotDeviceAuthReqDTO authReqDTO) {
-        return doPost("auth", authReqDTO);
+        return doPost("/auth", authReqDTO);
     }
 
     @SuppressWarnings("unchecked")
@@ -48,6 +49,7 @@ public class IotDeviceClientServiceImpl implements IotDeviceCommonApi {
             CommonResult<Boolean> result = restTemplate.postForObject(url, requestBody,
                     (Class<CommonResult<Boolean>>) (Class<?>) CommonResult.class);
             log.info("[doPost][url({}) requestBody({}) result({})]", url, requestBody, result);
+            Assert.notNull(result, "请求结果不能为空");
             return result;
         } catch (Exception e) {
             log.error("[doPost][url({}) requestBody({}) 发生异常]", url, requestBody, e);