This commit is contained in:
weiyachao 2023-09-20 20:26:12 +08:00
parent da921b81c1
commit 6ab572c789
7 changed files with 163 additions and 0 deletions

View File

@ -0,0 +1,18 @@
package com.qiuguo.iot.base.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 强制登陆
*
* @author weiyachao
* @since 2023/9/20 15:55
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Auth {
}

View File

@ -6,4 +6,6 @@ package com.qiuguo.iot.base.constans;
public class RedisConstans {
public static String DEVICE_INFO = "device::info::";
public static String IOT_TOKEN = "iot_token:";
}

View File

@ -0,0 +1,16 @@
package com.qiuguo.iot.base.constans;
/**
* XXX
*
* @author weiyachao 包含
* @since 2023/9/20 16:25
*/
public interface UserAuthContains {
String API_TOKEN = "Api-Token";
String API_TYPE = "Api-Type";
}

View File

@ -62,6 +62,11 @@
<version>${hsweb.orm.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis-reactive</artifactId>
</dependency>
<dependency>
<groupId>org.hswebframework.web</groupId>
<artifactId>hsweb-starter</artifactId>

View File

@ -4,10 +4,12 @@ import com.tuya.connector.spring.annotations.ConnectorScan;
import org.hswebframework.web.crud.annotation.EnableEasyormRepository;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
@SpringBootApplication(scanBasePackages = {"com.qiuguo.iot.user.api", "com.qiuguo.iot.data.service"})
@EnableEasyormRepository(value = "com.qiuguo.iot.data.entity.*")
@ConnectorScan(basePackages = "com.qiuguo.iot.user.api.service")
@EnableAspectJAutoProxy
public class IotBoxUserApiApplication {
public static void main(String[] args) {

View File

@ -0,0 +1,50 @@
package com.qiuguo.iot.user.api.config;
import com.qiuguo.iot.base.annotation.Auth;
import com.qiuguo.iot.base.constans.UserAuthContains;
import java.lang.reflect.Method;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.ReactiveStringRedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
/**
* XXX
*
* @author weiyachao
* @since 2023/9/20 18:50
*/
@Aspect
@Component
public class AuthAspect {
@Autowired
private ReactiveStringRedisTemplate reactiveRedisTemplate;
// @Autowired(required = false)
// private ServerWebExchange serverWebExchange;
//
// @Autowired
// private ServerHttpRequest httpServletRequest;
@Around("@annotation(com.qiuguo.iot.base.annotation.Auth)") // 切入点表达式这里使用了自定义注解
public Object authenticate(ProceedingJoinPoint joinPoint) throws Throwable {
// String first = httpServletRequest.getHeaders().getFirst(UserAuthContains.API_TOKEN);
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
Method method = signature.getMethod();
Auth annotation = method.getAnnotation(Auth.class);
System.out.println("annotation = " + annotation);
return joinPoint.proceed();
}
}

View File

@ -0,0 +1,70 @@
package com.qiuguo.iot.user.api.filter;
import com.qiuguo.iot.base.annotation.Auth;
import com.qiuguo.iot.base.constans.RedisConstans;
import com.qiuguo.iot.base.constans.UserAuthContains;
import java.lang.annotation.ElementType;
import java.time.Duration;
import java.util.Map;
import javax.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.data.redis.core.ReactiveRedisTemplate;
import org.springframework.data.redis.core.ReactiveStringRedisTemplate;
import org.springframework.util.ObjectUtils;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.WebFilter;
import org.springframework.web.server.WebFilterChain;
import org.springframework.web.servlet.HandlerMapping;
import reactor.core.publisher.Mono;
/**
* XXX
*
* @author weiyachao
* @since 2023/9/20 16:06
*/
@Configuration
@Slf4j
@Order(-1)
public class AuthFilter implements WebFilter {
// @Autowired
private ReactiveStringRedisTemplate reactiveRedisTemplate;
@Override
public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
HandlerMethod handlerMethod = exchange.getAttribute(HandlerMapping.BEST_MATCHING_HANDLER_ATTRIBUTE);
Object attribute = exchange.getAttribute("org.springframework.web.server.ServerWebExchange.LOG_ID");
System.out.println("attribute = " + attribute);
if (handlerMethod != null && handlerMethod.getMethod().isAnnotationPresent(Auth.class)) {
// 如果请求方法上有 Auth 注解执行登录验证逻辑
String api_token = exchange.getRequest().getHeaders().getFirst(UserAuthContains.API_TOKEN);
String api_type = exchange.getRequest().getHeaders().getFirst(UserAuthContains.API_TYPE);
if (ObjectUtils.isEmpty(api_token) || ObjectUtils.isEmpty(api_type)) {
return Mono.error(new RuntimeException("未登录"));
}
String key = RedisConstans.IOT_TOKEN.concat(api_token);
return reactiveRedisTemplate.getExpire(key).map(Duration::getSeconds).flatMap(ttl -> {
if (ttl == -1) {
// 用户没登陆
return Mono.error(new RuntimeException("未登录"));
} else if (ttl <= 3600) {
// token 将要失效
return reactiveRedisTemplate.expire(key, Duration.ofDays(7))
.then(chain.filter(exchange));
} else {
// 正常登录
return chain.filter(exchange);
}
});
}
return chain.filter(exchange);
}
}