105 lines
4.1 KiB
Java
105 lines
4.1 KiB
Java
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();
|
||
}
|
||
}
|