Commit a0a26c3d64fe25465b7367a6f8b5c43c1013d6d8
1 parent
643cc4cf
feat:【IoT 物联网】增加网关 HTTP 协议的鉴权,基于 JWT 轻量级(已测试)
Showing
5 changed files
with
19 additions
and
11 deletions
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 { |
| 179 | 179 | if(ex.getCause() instanceof InvalidFormatException) { |
| 180 | 180 | InvalidFormatException invalidFormatException = (InvalidFormatException) ex.getCause(); |
| 181 | 181 | return CommonResult.error(BAD_REQUEST.getCode(), String.format("请求参数类型错误:%s", invalidFormatException.getValue())); |
| 182 | - }else { | |
| 182 | + } else { | |
| 183 | 183 | return defaultExceptionHandler(ServletUtils.getRequest(), ex); |
| 184 | 184 | } |
| 185 | 185 | } | ... | ... |
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; |
| 10 | 10 | import org.springframework.context.annotation.Primary; |
| 11 | 11 | import org.springframework.validation.annotation.Validated; |
| 12 | 12 | import org.springframework.web.bind.annotation.PostMapping; |
| 13 | +import org.springframework.web.bind.annotation.RequestBody; | |
| 13 | 14 | import org.springframework.web.bind.annotation.RestController; |
| 14 | 15 | |
| 15 | 16 | import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; |
| ... | ... | @@ -30,7 +31,7 @@ public class IoTDeviceApiImpl implements IotDeviceCommonApi { |
| 30 | 31 | @Override |
| 31 | 32 | @PostMapping(RpcConstants.RPC_API_PREFIX + "/iot/device/auth") |
| 32 | 33 | @PermitAll |
| 33 | - public CommonResult<Boolean> authDevice(IotDeviceAuthReqDTO authReqDTO) { | |
| 34 | + public CommonResult<Boolean> authDevice(@RequestBody IotDeviceAuthReqDTO authReqDTO) { | |
| 34 | 35 | return success(deviceService.authDevice(authReqDTO)); |
| 35 | 36 | } |
| 36 | 37 | ... | ... |
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDeviceService.java
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; |
| 2 | 2 | |
| 3 | 3 | import cn.hutool.core.lang.Assert; |
| 4 | 4 | import cn.hutool.core.map.MapUtil; |
| 5 | +import cn.hutool.core.util.BooleanUtil; | |
| 5 | 6 | import cn.hutool.core.util.StrUtil; |
| 6 | 7 | import cn.hutool.extra.spring.SpringUtil; |
| 7 | 8 | import cn.iocoder.yudao.framework.common.pojo.CommonResult; |
| 8 | 9 | import cn.iocoder.yudao.module.iot.core.biz.IotDeviceCommonApi; |
| 9 | 10 | import cn.iocoder.yudao.module.iot.core.biz.dto.IotDeviceAuthReqDTO; |
| 11 | +import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage; | |
| 10 | 12 | import cn.iocoder.yudao.module.iot.core.mq.producer.IotDeviceMessageProducer; |
| 11 | 13 | import cn.iocoder.yudao.module.iot.core.util.IotDeviceAuthUtils; |
| 12 | 14 | import cn.iocoder.yudao.module.iot.gateway.protocol.http.IotHttpUpstreamProtocol; |
| ... | ... | @@ -47,7 +49,7 @@ public class IotHttpAuthHandler extends IotHttpAbstractHandler { |
| 47 | 49 | |
| 48 | 50 | @Override |
| 49 | 51 | public CommonResult<Object> handle0(RoutingContext context) { |
| 50 | - // 解析参数 | |
| 52 | + // 1. 解析参数 | |
| 51 | 53 | JsonObject body = context.body().asJsonObject(); |
| 52 | 54 | String clientId = body.getString("clientId"); |
| 53 | 55 | if (StrUtil.isEmpty(clientId)) { |
| ... | ... | @@ -62,20 +64,23 @@ public class IotHttpAuthHandler extends IotHttpAbstractHandler { |
| 62 | 64 | throw invalidParamException("password 不能为空"); |
| 63 | 65 | } |
| 64 | 66 | |
| 65 | - // 执行认证 | |
| 67 | + // 2.1 执行认证 | |
| 66 | 68 | CommonResult<Boolean> result = deviceClientService.authDevice(new IotDeviceAuthReqDTO() |
| 67 | 69 | .setClientId(clientId).setUsername(username).setPassword(password)); |
| 68 | - if (result == null || !result.isSuccess()) { | |
| 70 | + result.checkError();; | |
| 71 | + if (!BooleanUtil.isTrue(result.getData())) { | |
| 69 | 72 | throw exception(DEVICE_AUTH_FAIL); |
| 70 | 73 | } |
| 71 | - | |
| 72 | - // 生成 Token | |
| 74 | + // 2.2 生成 Token | |
| 73 | 75 | IotDeviceAuthUtils.DeviceInfo deviceInfo = deviceTokenService.parseUsername(username); |
| 74 | 76 | Assert.notNull(deviceInfo, "设备信息不能为空"); |
| 75 | 77 | String token = deviceTokenService.createToken(deviceInfo.getProductKey(), deviceInfo.getDeviceName()); |
| 76 | 78 | Assert.notBlank(token, "生成 token 不能为空位"); |
| 77 | 79 | |
| 78 | - // TODO @芋艿:发送上线消息; | |
| 80 | + // 3. 执行上线 | |
| 81 | + deviceMessageProducer.sendDeviceMessage(IotDeviceMessage.of(deviceInfo.getProductKey(), deviceInfo.getDeviceName(), | |
| 82 | + protocol.getServerId()) | |
| 83 | + .ofStateOnline()); | |
| 79 | 84 | |
| 80 | 85 | // 构建响应数据 |
| 81 | 86 | return success(MapUtil.of("token", token)); | ... | ... |
yudao-module-iot/yudao-module-iot-gateway/src/main/java/cn/iocoder/yudao/module/iot/gateway/service/device/IotDeviceClientServiceImpl.java
| 1 | 1 | package cn.iocoder.yudao.module.iot.gateway.service.device; |
| 2 | 2 | |
| 3 | +import cn.hutool.core.lang.Assert; | |
| 3 | 4 | import cn.iocoder.yudao.framework.common.pojo.CommonResult; |
| 4 | 5 | import cn.iocoder.yudao.module.iot.core.biz.IotDeviceCommonApi; |
| 5 | 6 | import cn.iocoder.yudao.module.iot.core.biz.dto.IotDeviceAuthReqDTO; |
| ... | ... | @@ -31,7 +32,7 @@ public class IotDeviceClientServiceImpl implements IotDeviceCommonApi { |
| 31 | 32 | public void init() { |
| 32 | 33 | IotGatewayProperties.RpcProperties rpc = gatewayProperties.getRpc(); |
| 33 | 34 | restTemplate = new RestTemplateBuilder() |
| 34 | - .rootUri(rpc.getUrl() + "/rpc-api/iot/device/") | |
| 35 | + .rootUri(rpc.getUrl() + "/rpc-api/iot/device") | |
| 35 | 36 | .readTimeout(rpc.getReadTimeout()) |
| 36 | 37 | .connectTimeout(rpc.getConnectTimeout()) |
| 37 | 38 | .build(); |
| ... | ... | @@ -39,7 +40,7 @@ public class IotDeviceClientServiceImpl implements IotDeviceCommonApi { |
| 39 | 40 | |
| 40 | 41 | @Override |
| 41 | 42 | public CommonResult<Boolean> authDevice(IotDeviceAuthReqDTO authReqDTO) { |
| 42 | - return doPost("auth", authReqDTO); | |
| 43 | + return doPost("/auth", authReqDTO); | |
| 43 | 44 | } |
| 44 | 45 | |
| 45 | 46 | @SuppressWarnings("unchecked") |
| ... | ... | @@ -48,6 +49,7 @@ public class IotDeviceClientServiceImpl implements IotDeviceCommonApi { |
| 48 | 49 | CommonResult<Boolean> result = restTemplate.postForObject(url, requestBody, |
| 49 | 50 | (Class<CommonResult<Boolean>>) (Class<?>) CommonResult.class); |
| 50 | 51 | log.info("[doPost][url({}) requestBody({}) result({})]", url, requestBody, result); |
| 52 | + Assert.notNull(result, "请求结果不能为空"); | |
| 51 | 53 | return result; |
| 52 | 54 | } catch (Exception e) { |
| 53 | 55 | log.error("[doPost][url({}) requestBody({}) 发生异常]", url, requestBody, e); | ... | ... |