添加登录拦截器

This commit is contained in:
weiyachao 2023-09-21 18:24:27 +08:00
parent 4685991a2b
commit 962ea083f0
10 changed files with 155 additions and 55 deletions

View File

@ -1,18 +0,0 @@
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

@ -59,6 +59,16 @@
<version>1.2.83</version> <version>1.2.83</version>
<scope>compile</scope> <scope>compile</scope>
</dependency> </dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis-reactive</artifactId>
</dependency>
<dependency>
<groupId>com.qiuguo.iot</groupId>
<artifactId>iot-base</artifactId>
<version>0.0.1-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
</dependencies> </dependencies>

View File

@ -13,8 +13,8 @@ import org.springframework.web.filter.CorsFilter;
* 全局跨域配置. * 全局跨域配置.
* *
*/ */
@AutoConfiguration // @AutoConfiguration
@EnableConfigurationProperties(CorsProperties.class) // @EnableConfigurationProperties(CorsProperties.class)
public class GlobalCorsConfiguration { public class GlobalCorsConfiguration {
/** /**
@ -22,8 +22,8 @@ public class GlobalCorsConfiguration {
* *
* @param corsProperties 跨域配置 * @param corsProperties 跨域配置
*/ */
@Bean // @Bean
@ConditionalOnMissingBean(CorsFilter.class) // @ConditionalOnMissingBean(CorsFilter.class)
public CorsFilter corsFilter(CorsProperties corsProperties) { public CorsFilter corsFilter(CorsProperties corsProperties) {
CorsConfiguration config = new CorsConfiguration(); CorsConfiguration config = new CorsConfiguration();
// 设置允许跨域访问的域名 // 设置允许跨域访问的域名

View File

@ -13,7 +13,7 @@ import org.springframework.boot.context.properties.ConfigurationProperties;
*/ */
@Getter @Getter
@Setter @Setter
@ConfigurationProperties(prefix = "application.cors") // @ConfigurationProperties(prefix = "application.cors")
public class CorsProperties { public class CorsProperties {
/** /**

View File

@ -0,0 +1,69 @@
package com.qiuguo.iot.gateway.filter;
import com.qiuguo.iot.base.constans.RedisConstans;
import com.qiuguo.iot.base.constans.UserAuthContains;
import com.qiuguo.iot.gateway.config.properties.XssProperties;
import java.time.Duration;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.data.redis.core.ReactiveStringRedisTemplate;
import org.springframework.http.server.RequestPath;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
/**
* XXX
*
* @author weiyachao
* @since 2023/9/21 17:56
*/
@Component
@Slf4j
public class AuthFilter implements GlobalFilter, Ordered {
@Autowired
private ReactiveStringRedisTemplate reactiveRedisTemplate;
@Autowired
private XssProperties xssProperties;
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
ServerHttpRequest request = exchange.getRequest();
String url = request.getURI().toString();
if (xssProperties.getExcludeUrls().contains(url)) {
return chain.filter(exchange);
}
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);
}
});
}
@Override
public int getOrder() {
return -1;
}
}

View File

@ -19,4 +19,35 @@ spring:
# 共享配置 # 共享配置
shared-configs: shared-configs:
- application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension} - application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}
gateway:
discovery:
locator:
# 开启服务发现
enabled: true
# 忽略注册中心服务的大小写
lower-case-service-id: true
globalcors:
corsConfigurations:
'[/**]':
# 允许携带认证信息
allow-credentials: true
# 允许跨域的源(网站域名/ip),设置*为全部
allowedOriginPatterns: "*"
# 允许跨域的method 默认为GET和OPTIONS设置*为全部
allowedMethods: "*"
# 允许跨域请求里的head字段设置*为全部
allowedHeaders: "*"
routes:
# 安全配置
security:
# 防止XSS攻击
xss:
enabled: true
# 排除的路径
exclude-urls:
- /ehs-audit/web/audit-content
application:
cors:
allowed-crigin-patterns:

View File

@ -1,9 +1,16 @@
package com.qiuguo.iot.user.api.controller.user; package com.qiuguo.iot.user.api.controller.user;
import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.JSONObject;
import com.qiuguo.iot.base.constans.RedisConstans;
import com.qiuguo.iot.base.constans.UserAuthContains;
import java.time.Duration;
import java.util.Objects; import java.util.Objects;
import javax.annotation.Resource;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.ReactiveRedisTemplate;
import org.springframework.data.redis.core.ReactiveStringRedisTemplate;
import org.springframework.http.HttpHeaders; import org.springframework.http.HttpHeaders;
import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap; import org.springframework.util.MultiValueMap;
@ -31,7 +38,7 @@ import static org.springframework.http.MediaType.APPLICATION_FORM_URLENCODED_VAL
public class UserController { public class UserController {
private final WebClient webClient = WebClient.builder() private final WebClient webClient = WebClient.builder()
.defaultHeader(HttpHeaders.CONTENT_TYPE,APPLICATION_FORM_URLENCODED_VALUE) .defaultHeader(HttpHeaders.CONTENT_TYPE,APPLICATION_FORM_URLENCODED_VALUE)
.defaultHeader("Api-Type","web") .defaultHeader("Api-Type","iot")
.build(); .build();
@Value("${userUrl.baseUrl}") @Value("${userUrl.baseUrl}")
@ -64,12 +71,15 @@ public class UserController {
@Value("${userUrl.editUserInfoUrl}") @Value("${userUrl.editUserInfoUrl}")
private String editUserInfoUrl; private String editUserInfoUrl;
@Resource
private ReactiveStringRedisTemplate reactiveStringRedisTemplate;
/** /**
* 修改登录密码-auth * 修改登录密码-auth
*/ */
@PostMapping("/change") @PostMapping("/change")
public Mono<JSONObject> change(@RequestBody JSONObject jsonObject, @RequestHeader("Api-Token") String token, public Mono<JSONObject> change(@RequestBody JSONObject jsonObject, @RequestHeader(UserAuthContains.API_TOKEN) String token,
@RequestHeader("Api-Type") String type) { @RequestHeader(UserAuthContains.API_TYPE) String type) {
WebClient authWebClient = getAuthWebClient(token, type); WebClient authWebClient = getAuthWebClient(token, type);
return authWebClient.post().uri(baseUrl + changeUrl).bodyValue(getMultiValueMap(jsonObject)).retrieve() return authWebClient.post().uri(baseUrl + changeUrl).bodyValue(getMultiValueMap(jsonObject)).retrieve()
.bodyToMono(JSONObject.class).doOnNext(res -> { .bodyToMono(JSONObject.class).doOnNext(res -> {
@ -83,8 +93,8 @@ public class UserController {
* 账号注销-auth * 账号注销-auth
*/ */
@PostMapping("/userCance") @PostMapping("/userCance")
public Mono<JSONObject> userCance(@RequestBody JSONObject jsonObject, @RequestHeader("Api-Token") String token, public Mono<JSONObject> userCance(@RequestBody JSONObject jsonObject, @RequestHeader(UserAuthContains.API_TOKEN) String token,
@RequestHeader("Api-Type") String type) { @RequestHeader(UserAuthContains.API_TYPE) String type) {
return getAuthWebClient(token, type).post().uri(baseUrl + userCancelUrl) return getAuthWebClient(token, type).post().uri(baseUrl + userCancelUrl)
.bodyValue(getMultiValueMap(jsonObject)) .bodyValue(getMultiValueMap(jsonObject))
.retrieve() .retrieve()
@ -99,8 +109,8 @@ public class UserController {
* 修改用户信息-auth * 修改用户信息-auth
*/ */
@PostMapping("/edit/userInfo") @PostMapping("/edit/userInfo")
public Mono<JSONObject> editUserInfo(@RequestBody JSONObject jsonObject, @RequestHeader("Api-Token") String token, public Mono<JSONObject> editUserInfo(@RequestBody JSONObject jsonObject, @RequestHeader(UserAuthContains.API_TOKEN) String token,
@RequestHeader("Api-Type") String type) { @RequestHeader(UserAuthContains.API_TYPE) String type) {
return webClient.mutate() return webClient.mutate()
.defaultHeader("Api-Token", token) .defaultHeader("Api-Token", token)
.defaultHeader("Api-Type", type).build().post().uri(editUserInfoUrl) .defaultHeader("Api-Type", type).build().post().uri(editUserInfoUrl)
@ -117,8 +127,8 @@ public class UserController {
* 个人信息管理-auth * 个人信息管理-auth
*/ */
@GetMapping("/userInfo") @GetMapping("/userInfo")
public Mono<JSONObject> getUserInfo(@RequestHeader("Api-Token") String token, public Mono<JSONObject> getUserInfo(@RequestHeader(UserAuthContains.API_TOKEN) String token,
@RequestHeader("Api-Type") String type) { @RequestHeader(UserAuthContains.API_TYPE) String type) {
return getAuthWebClient(token, type).get().uri(userInfoUrl).retrieve() return getAuthWebClient(token, type).get().uri(userInfoUrl).retrieve()
.bodyToMono(JSONObject.class).doOnNext(res -> { .bodyToMono(JSONObject.class).doOnNext(res -> {
if (!Objects.equals(res.getInteger("code"), 200)) { if (!Objects.equals(res.getInteger("code"), 200)) {
@ -131,8 +141,8 @@ public class UserController {
* 是否设置登录密码-auth * 是否设置登录密码-auth
*/ */
@GetMapping("/first/password") @GetMapping("/first/password")
public Mono<JSONObject> firstPassword(@RequestHeader("Api-Token") String token, public Mono<JSONObject> firstPassword(@RequestHeader(UserAuthContains.API_TOKEN) String token,
@RequestHeader("Api-Type") String type) { @RequestHeader(UserAuthContains.API_TYPE) String type) {
return getAuthWebClient(token, type).get().uri(firstPasswordUrl).retrieve() return getAuthWebClient(token, type).get().uri(firstPasswordUrl).retrieve()
.bodyToMono(JSONObject.class).doOnNext(res -> { .bodyToMono(JSONObject.class).doOnNext(res -> {
if (!Objects.equals(res.getInteger("code"), 200)) { if (!Objects.equals(res.getInteger("code"), 200)) {
@ -166,7 +176,9 @@ public class UserController {
.retrieve().bodyToMono(JSONObject.class).flatMap(res -> { .retrieve().bodyToMono(JSONObject.class).flatMap(res -> {
if (Objects.equals(res.getInteger("code"), 1) && !res.getString("info") if (Objects.equals(res.getInteger("code"), 1) && !res.getString("info")
.contains("该手机号还没有注册哦")) { .contains("该手机号还没有注册哦")) {
return Mono.just(res); String token = res.getJSONObject("data").getJSONObject("token").getString("token");
return reactiveStringRedisTemplate.opsForValue()
.set(RedisConstans.IOT_TOKEN.concat(token), token, Duration.ofDays(7)).then(Mono.just(res));
} else if(!res.getString("info").contains("该手机号还没有注册哦")){ } else if(!res.getString("info").contains("该手机号还没有注册哦")){
return Mono.error(new RuntimeException(res.getString("info"))); return Mono.error(new RuntimeException(res.getString("info")));
}else { }else {
@ -186,10 +198,14 @@ public class UserController {
object.add("phone", jsonObject.getString("phone")); object.add("phone", jsonObject.getString("phone"));
object.add("verify", jsonObject.getString("verify")); object.add("verify", jsonObject.getString("verify"));
return webClient.post().uri(baseUrl + smsUrl).bodyValue(object).retrieve() return webClient.post().uri(baseUrl + smsUrl).bodyValue(object).retrieve()
.bodyToMono(JSONObject.class).doOnNext(twoRes -> { .bodyToMono(JSONObject.class).flatMap(twoRes -> {
if (!Objects.equals(twoRes.getInteger("code"), 1)) { if (!Objects.equals(twoRes.getInteger("code"), 1)) {
throw new RuntimeException(twoRes.getString("info")); return Mono.error(new RuntimeException(twoRes.getString("info")));
} }
String token = res.getJSONObject("data").getJSONObject("token").getString("token");
return reactiveStringRedisTemplate.opsForValue()
.set(RedisConstans.IOT_TOKEN.concat(token), token, Duration.ofDays(7)).then(Mono.just(res));
}); });
} }
}); });
@ -205,11 +221,15 @@ public class UserController {
log.info("UserController[]loginByPwd[]jsonObject:{}", jsonObject); log.info("UserController[]loginByPwd[]jsonObject:{}", jsonObject);
return webClient.post().uri(baseUrl + pwdUrl).bodyValue(getMultiValueMap(jsonObject)).retrieve() return webClient.post().uri(baseUrl + pwdUrl).bodyValue(getMultiValueMap(jsonObject)).retrieve()
.bodyToMono(JSONObject.class) .bodyToMono(JSONObject.class)
.doOnNext(res -> { .flatMap(res -> {
if (!Objects.equals(res.getInteger("code"), 1)) { if (!Objects.equals(res.getInteger("code"), 1)) {
throw new RuntimeException(res.getString("info")); return Mono.error(new RuntimeException(res.getString("info")));
} }
String token = res.getJSONObject("data").getJSONObject("token").getString("token");
return reactiveStringRedisTemplate.opsForValue()
.set(RedisConstans.IOT_TOKEN.concat(token), token, Duration.ofDays(7)).then(Mono.just(res));
}); });
} }
private MultiValueMap<String,String> getMultiValueMap(JSONObject jsonObject) { private MultiValueMap<String,String> getMultiValueMap(JSONObject jsonObject) {

View File

@ -1,21 +1,9 @@
package com.qiuguo.iot.user.api.filter; 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 lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order; import org.springframework.core.annotation.Order;
import org.springframework.data.redis.core.ReactiveRedisTemplate;
import org.springframework.data.redis.core.ReactiveStringRedisTemplate; 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.ServerWebExchange;
import org.springframework.web.server.WebFilter; import org.springframework.web.server.WebFilter;
import org.springframework.web.server.WebFilterChain; import org.springframework.web.server.WebFilterChain;

View File

@ -10,10 +10,10 @@ spring:
nacos: nacos:
discovery: discovery:
# 服务注册地址 # 服务注册地址
server-addr: 172.24.218.235:8848/ server-addr: 192.168.8.146:32470
config: config:
# 配置中心地址 # 配置中心地址
server-addr: 172.24.218.235:8848/ server-addr: 192.168.8.146:32470
# 配置文件格式 # 配置文件格式
file-extension: yml file-extension: yml
# 共享配置 # 共享配置

View File

@ -18,7 +18,7 @@ import org.springframework.boot.test.context.SpringBootTest;
@Slf4j @Slf4j
public class UserTest { public class UserTest {
public String deviceId = "6c4a153095be2b7f8baofp"; public String deviceId = "6cae26f5512eee7c12aqd9";
public String spaceId = "163257138"; public String spaceId = "163257138";
@ -88,7 +88,7 @@ public class UserTest {
JSONObject js3 = new JSONObject(); JSONObject js3 = new JSONObject();
js3.put("code", "bright_value_v2"); js3.put("code", "bright_value_v2");
js3.put("value", 10); js3.put("value", 10);
commands.put("commands", Arrays.asList( js3)); commands.put("commands", Arrays.asList(jsonObject));
Object controlDevice = tuyaDeviceConnector.controlDevice(deviceId,commands); Object controlDevice = tuyaDeviceConnector.controlDevice(deviceId,commands);
System.out.println(controlDevice); System.out.println(controlDevice);