@@ -0,0 +1,104 @@
|
||||
package com.yunhai.acaclassroom.aspect;
|
||||
|
||||
import com.yunhai.acaclassroom.utils.UserContext;
|
||||
import com.yunhai.platform.auth.BoaUserContext;
|
||||
import com.yunhai.platform.utils.model.BoaUser;
|
||||
import org.aspectj.lang.ProceedingJoinPoint;
|
||||
import org.aspectj.lang.annotation.Around;
|
||||
import org.aspectj.lang.annotation.Aspect;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.context.request.RequestContextHolder;
|
||||
import org.springframework.web.context.request.ServletRequestAttributes;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
/**
|
||||
* 把基础平台的当前登录用户({@link BoaUser})复制到自有 {@link UserContext}(ThreadLocal),请求结束清理。
|
||||
* <p>参照 UserclassService 的 ControllerUserContextAspect:优先从控制器入参里的 {@code BoaUser} 取,
|
||||
* 否则回退到框架 {@code BoaUserContext#get()}。本模块为纯教师端,无视角切换。</p>
|
||||
*/
|
||||
@Aspect
|
||||
@Component
|
||||
@Order(1)
|
||||
public class ControllerUserContextAspect {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(ControllerUserContextAspect.class);
|
||||
|
||||
/** 本地联调开关(默认关闭):无 SSO 会话时用固定开发身份填充 UserContext,便于无登录端到端联调。生产严禁开启。 */
|
||||
@Value("${acaclassroom.dev-context.enabled:false}")
|
||||
private boolean devContextEnabled;
|
||||
|
||||
@Around("execution(* com.yunhai.acaclassroom.controller..*.*(..))")
|
||||
public Object around(ProceedingJoinPoint pjp) throws Throwable {
|
||||
try {
|
||||
BoaUser boaUser = resolveBoaUser(pjp.getArgs());
|
||||
UserContext.UserInfo info = new UserContext.UserInfo();
|
||||
if (boaUser != null) {
|
||||
info.userId = boaUser.getId();
|
||||
info.userName = boaUser.getName();
|
||||
info.type = boaUser.getType();
|
||||
if (boaUser.getCurrentRole() != null) {
|
||||
info.schId = boaUser.getCurrentRole().getSchId();
|
||||
} else if (boaUser.getSchool() != null) {
|
||||
info.schId = boaUser.getSchool().getId();
|
||||
}
|
||||
if (boaUser.getRoleIds() != null && !boaUser.getRoleIds().isEmpty()) {
|
||||
info.roleId = boaUser.getRoleIds().get(0);
|
||||
}
|
||||
} else if (devContextEnabled) {
|
||||
info.userId = 99999;
|
||||
info.userName = "本地开发";
|
||||
info.schId = 1;
|
||||
log.debug("[UserContext] 无 SSO 会话,已使用本地开发身份(schId=1)");
|
||||
}
|
||||
info.ip = clientIp();
|
||||
UserContext.set(info);
|
||||
return pjp.proceed();
|
||||
} finally {
|
||||
UserContext.clear();
|
||||
}
|
||||
}
|
||||
|
||||
/** 控制器入参中若声明了 BoaUser(框架有参数解析器注入),优先用它;否则取 ThreadLocal 门面。 */
|
||||
private BoaUser resolveBoaUser(Object[] args) {
|
||||
if (args != null) {
|
||||
for (Object a : args) {
|
||||
if (a instanceof BoaUser) {
|
||||
return (BoaUser) a;
|
||||
}
|
||||
}
|
||||
}
|
||||
try {
|
||||
return BoaUserContext.get();
|
||||
} catch (Exception e) {
|
||||
log.debug("[UserContext] 读取 BoaUserContext 失败: {}", e.getMessage());
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private HttpServletRequest request() {
|
||||
Object attrs = RequestContextHolder.getRequestAttributes();
|
||||
return attrs instanceof ServletRequestAttributes ? ((ServletRequestAttributes) attrs).getRequest() : null;
|
||||
}
|
||||
|
||||
private String clientIp() {
|
||||
HttpServletRequest req = request();
|
||||
if (req == null) {
|
||||
return null;
|
||||
}
|
||||
String ip = req.getHeader("X-Forwarded-For");
|
||||
if (ip != null && !ip.isEmpty()) {
|
||||
int comma = ip.indexOf(',');
|
||||
return comma > 0 ? ip.substring(0, comma).trim() : ip.trim();
|
||||
}
|
||||
ip = req.getHeader("X-Real-IP");
|
||||
if (ip != null && !ip.isEmpty()) {
|
||||
return ip.trim();
|
||||
}
|
||||
return req.getRemoteAddr();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user