Commit 083dac77e1ef5e6bc04ce09fe03c31258e2ed93a

Authored by YunaiV
1 parent cbb11986

接入登陆日志

Showing 17 changed files with 236 additions and 52 deletions
ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/SysLogininforController.java
1 1 package com.ruoyi.web.controller.monitor;
2 2  
3 3 import java.util.List;
  4 +
4 5 import org.springframework.beans.factory.annotation.Autowired;
5 6 import org.springframework.security.access.prepost.PreAuthorize;
6 7 import org.springframework.web.bind.annotation.DeleteMapping;
... ... @@ -24,15 +25,14 @@ import com.ruoyi.system.service.ISysLogininforService;
24 25 */
25 26 @RestController
26 27 @RequestMapping("/monitor/logininfor")
27   -public class SysLogininforController extends BaseController
28   -{
  28 +public class SysLogininforController extends BaseController {
  29 +
29 30 @Autowired
30 31 private ISysLogininforService logininforService;
31 32  
32 33 @PreAuthorize("@ss.hasPermi('monitor:logininfor:list')")
33 34 @GetMapping("/list")
34   - public TableDataInfo list(SysLogininfor logininfor)
35   - {
  35 + public TableDataInfo list(SysLogininfor logininfor) {
36 36 startPage();
37 37 List<SysLogininfor> list = logininforService.selectLogininforList(logininfor);
38 38 return getDataTable(list);
... ... @@ -41,8 +41,7 @@ public class SysLogininforController extends BaseController
41 41 @Log(title = "登录日志", businessType = BusinessType.EXPORT)
42 42 @PreAuthorize("@ss.hasPermi('monitor:logininfor:export')")
43 43 @GetMapping("/export")
44   - public AjaxResult export(SysLogininfor logininfor)
45   - {
  44 + public AjaxResult export(SysLogininfor logininfor) {
46 45 List<SysLogininfor> list = logininforService.selectLogininforList(logininfor);
47 46 ExcelUtil<SysLogininfor> util = new ExcelUtil<SysLogininfor>(SysLogininfor.class);
48 47 return util.exportExcel(list, "登录日志");
... ...
src/main/java/cn/iocoder/dashboard/framework/logger/operatelog/core/aop/OperateLogAspect.java
... ... @@ -24,9 +24,6 @@ import org.aspectj.lang.reflect.MethodSignature;
24 24 import org.springframework.core.annotation.AnnotationUtils;
25 25 import org.springframework.web.bind.annotation.RequestMapping;
26 26 import org.springframework.web.bind.annotation.RequestMethod;
27   -import org.springframework.web.context.request.RequestAttributes;
28   -import org.springframework.web.context.request.RequestContextHolder;
29   -import org.springframework.web.context.request.ServletRequestAttributes;
30 27 import org.springframework.web.multipart.MultipartFile;
31 28  
32 29 import javax.annotation.Resource;
... ... @@ -196,11 +193,10 @@ public class OperateLogAspect {
196 193  
197 194 private static void fillRequestFields(SysOperateLogCreateReqVO operateLogVO) {
198 195 // 获得 Request 对象
199   - RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
200   - if (!(requestAttributes instanceof ServletRequestAttributes)) {
  196 + HttpServletRequest request = ServletUtils.getRequest();
  197 + if (request == null) {
201 198 return;
202 199 }
203   - HttpServletRequest request = ((ServletRequestAttributes) requestAttributes).getRequest();
204 200 // 补全请求信息
205 201 operateLogVO.setRequestMethod(request.getMethod());
206 202 operateLogVO.setRequestUrl(request.getRequestURI());
... ...
src/main/java/cn/iocoder/dashboard/modules/system/controller/logger/SysLoginLogController.java 0 → 100644
  1 +package cn.iocoder.dashboard.modules.system.controller.logger;
  2 +
  3 +public class SysLoginLogController {
  4 +}
... ...
src/main/java/cn/iocoder/dashboard/modules/system/controller/logger/vo/loginlog/SysLoginLogBaseVO.java
... ... @@ -15,27 +15,23 @@ import javax.validation.constraints.Size;
15 15 @Data
16 16 public class SysLoginLogBaseVO {
17 17  
  18 + @ApiModelProperty(value = "日志类型", required = true, example = "1", notes = "参见 SysLoginLogTypeEnum 枚举类")
  19 + @NotNull(message = "日志类型不能为空")
  20 + private Integer logType;
  21 +
18 22 @ApiModelProperty(value = "链路追踪编号", required = true, example = "89aca178-a370-411c-ae02-3f0d672be4ab")
19 23 @NotEmpty(message = "链路追踪编号不能为空")
20 24 private String traceId;
21 25  
22   - @ApiModelProperty(value = "用户编号", required = true, example = "1024")
23   - @NotNull(message = "用户编号不能为空")
24   - private Long userId;
25   -
26 26 @ApiModelProperty(value = "用户账号", required = true, example = "yudao")
27 27 @NotBlank(message = "用户账号不能为空")
28 28 @Size(max = 30, message = "用户账号长度不能超过30个字符")
29 29 private String username;
30 30  
31   -
32 31 @ApiModelProperty(value = "登陆结果", required = true, example = "1", notes = "参见 SysLoginResultEnum 枚举类")
33 32 @NotNull(message = "登陆结果不能为空")
34 33 private Integer result;
35 34  
36   - @ApiModelProperty(value = "操作明细", example = "修改编号为 1 的用户信息,将性别从男改成女,将姓名从芋道改成源码。")
37   - private String content;
38   -
39 35 @ApiModelProperty(value = "用户 IP", required = true, example = "127.0.0.1")
40 36 @NotEmpty(message = "用户 IP 不能为空")
41 37 private String userIp;
... ...
src/main/java/cn/iocoder/dashboard/modules/system/controller/logger/vo/loginlog/SysLoginLogCreateReqVO.java
1 1 package cn.iocoder.dashboard.modules.system.controller.logger.vo.loginlog;
2 2  
3   -import cn.iocoder.dashboard.modules.system.controller.logger.vo.operatelog.SysOperateLogCreateReqVO;
4 3 import io.swagger.annotations.ApiModel;
5 4 import lombok.Data;
6 5 import lombok.EqualsAndHashCode;
... ... @@ -11,5 +10,5 @@ import lombok.ToString;
11 10 @Data
12 11 @EqualsAndHashCode(callSuper = true)
13 12 @ToString(callSuper = true)
14   -public class SysLoginLogCreateReqVO extends SysOperateLogCreateReqVO {
  13 +public class SysLoginLogCreateReqVO extends SysLoginLogBaseVO {
15 14 }
... ...
src/main/java/cn/iocoder/dashboard/modules/system/convert/logger/SysLoginLogConvert.java 0 → 100644
  1 +package cn.iocoder.dashboard.modules.system.convert.logger;
  2 +
  3 +import cn.iocoder.dashboard.modules.system.controller.logger.vo.loginlog.SysLoginLogCreateReqVO;
  4 +import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.logger.SysLoginLogDO;
  5 +import org.mapstruct.Mapper;
  6 +import org.mapstruct.factory.Mappers;
  7 +
  8 +@Mapper
  9 +public interface SysLoginLogConvert {
  10 +
  11 + SysLoginLogConvert INSTANCE = Mappers.getMapper(SysLoginLogConvert.class);
  12 +
  13 + SysLoginLogDO convert(SysLoginLogCreateReqVO bean);
  14 +
  15 +}
... ...
src/main/java/cn/iocoder/dashboard/modules/system/dal/mysql/dao/logger/SysLoginLogMapper.java 0 → 100644
  1 +package cn.iocoder.dashboard.modules.system.dal.mysql.dao.logger;
  2 +
  3 +import cn.iocoder.dashboard.framework.mybatis.core.mapper.BaseMapperX;
  4 +import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.logger.SysLoginLogDO;
  5 +import org.apache.ibatis.annotations.Mapper;
  6 +
  7 +@Mapper
  8 +public interface SysLoginLogMapper extends BaseMapperX<SysLoginLogDO> {
  9 +}
... ...
src/main/java/cn/iocoder/dashboard/modules/system/dal/mysql/dataobject/logger/SysLoginLogDO.java
1 1 package cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.logger;
2 2  
3 3 import cn.iocoder.dashboard.framework.mybatis.core.dataobject.BaseDO;
4   -import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.user.SysUserDO;
  4 +import cn.iocoder.dashboard.modules.system.enums.logger.SysLoginLogTypeEnum;
5 5 import cn.iocoder.dashboard.modules.system.enums.logger.SysLoginResultEnum;
6 6 import com.baomidou.mybatisplus.annotation.TableName;
  7 +import lombok.Data;
  8 +import lombok.EqualsAndHashCode;
  9 +import lombok.ToString;
7 10  
8 11 /**
9   - * 系统访问记录表
  12 + * 登陆日志表
  13 + *
  14 + * 注意,包括登陆和登出两种行为
10 15 *
11 16 * @author ruoyi
12 17 */
13   -@TableName("用户登陆日志")
  18 +@TableName("sys_login_log")
  19 +@Data
  20 +@EqualsAndHashCode(callSuper = true)
  21 +@ToString(callSuper = true)
14 22 public class SysLoginLogDO extends BaseDO {
15 23  
16 24 /**
... ... @@ -18,15 +26,15 @@ public class SysLoginLogDO extends BaseDO {
18 26 */
19 27 private Long id;
20 28 /**
21   - * 链路追踪编号
  29 + * 日志类型
  30 + *
  31 + * 枚举 {@link SysLoginLogTypeEnum}
22 32 */
23   - private String traceId;
  33 + private Integer logType;
24 34 /**
25   - * 用户编号
26   - *
27   - * 外键 {@link SysUserDO#getId()}
  35 + * 链路追踪编号
28 36 */
29   - private Long userId;
  37 + private String traceId;
30 38 /**
31 39 * 用户账号
32 40 *
... ... @@ -39,12 +47,10 @@ public class SysLoginLogDO extends BaseDO {
39 47 * 枚举 {@link SysLoginResultEnum}
40 48 */
41 49 private Integer result;
42   -
43 50 /**
44 51 * 用户 IP
45 52 */
46 53 private String userIp;
47   -
48 54 /**
49 55 * 浏览器 UA
50 56 */
... ...
src/main/java/cn/iocoder/dashboard/modules/system/enums/SysErrorCodeConstants.java
... ... @@ -13,6 +13,8 @@ public interface SysErrorCodeConstants {
13 13 ErrorCode AUTH_LOGIN_BAD_CREDENTIALS = new ErrorCode(1002000000, "登录失败,账号密码不正确");
14 14 ErrorCode AUTH_LOGIN_USER_DISABLED = new ErrorCode(1002000001, "登录失败,账号被禁用");
15 15 ErrorCode AUTH_LOGIN_FAIL_UNKNOWN = new ErrorCode(1002000002, "登录失败"); // 登陆失败的兜底,位置原因
  16 + ErrorCode AUTH_LOGIN_CAPTCHA_NOT_FOUND = new ErrorCode(1002000003, "验证码不存在");
  17 + ErrorCode AUTH_LOGIN_CAPTCHA_CODE_ERROR = new ErrorCode(1002000004, "验证码不正确");
16 18  
17 19 // ========== TOKEN 模块 1002001000 ==========
18 20 ErrorCode TOKEN_EXPIRED = new ErrorCode(1002001000, "Token 已经过期");
... ...
src/main/java/cn/iocoder/dashboard/modules/system/enums/logger/SysLoginLogTypeEnum.java 0 → 100644
  1 +package cn.iocoder.dashboard.modules.system.enums.logger;
  2 +
  3 +import lombok.AllArgsConstructor;
  4 +import lombok.Getter;
  5 +
  6 +/**
  7 + * 登陆日志的类型枚举
  8 + */
  9 +@Getter
  10 +@AllArgsConstructor
  11 +public enum SysLoginLogTypeEnum {
  12 +
  13 + LOGIN(1),
  14 + LOGOUT(2);
  15 +
  16 + /**
  17 + * 日志类型
  18 + */
  19 + private final Integer type;
  20 +
  21 +}
... ...
src/main/java/cn/iocoder/dashboard/modules/system/enums/logger/SysLoginResultEnum.java
... ... @@ -11,6 +11,12 @@ import lombok.Getter;
11 11 public enum SysLoginResultEnum {
12 12  
13 13 SUCCESS(0), // 成功
  14 + BAD_CREDENTIALS(10), // 账号或密码不正确
  15 + USER_DISABLED(20), // 账号或密码不正确
  16 + CAPTCHA_NOT_FOUND(30), // 验证码不存在
  17 + CAPTCHA_CODE_ERROR(31), // 验证码不正确
  18 +
  19 + UNKNOWN_ERROR(100), // 未知异常
14 20 ;
15 21  
16 22 /**
... ...
src/main/java/cn/iocoder/dashboard/modules/system/service/auth/impl/SysAuthServiceImpl.java
... ... @@ -3,16 +3,24 @@ package cn.iocoder.dashboard.modules.system.service.auth.impl;
3 3 import cn.hutool.core.util.IdUtil;
4 4 import cn.hutool.core.util.StrUtil;
5 5 import cn.iocoder.dashboard.common.enums.CommonStatusEnum;
  6 +import cn.iocoder.dashboard.common.exception.util.ServiceExceptionUtil;
6 7 import cn.iocoder.dashboard.framework.security.config.SecurityProperties;
7 8 import cn.iocoder.dashboard.framework.security.core.LoginUser;
  9 +import cn.iocoder.dashboard.framework.tracer.core.util.TracerUtils;
  10 +import cn.iocoder.dashboard.modules.system.controller.logger.vo.loginlog.SysLoginLogCreateReqVO;
8 11 import cn.iocoder.dashboard.modules.system.convert.auth.SysAuthConvert;
9 12 import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.user.SysUserDO;
10 13 import cn.iocoder.dashboard.modules.system.dal.redis.dao.auth.SysLoginUserRedisDAO;
  14 +import cn.iocoder.dashboard.modules.system.enums.logger.SysLoginLogTypeEnum;
  15 +import cn.iocoder.dashboard.modules.system.enums.logger.SysLoginResultEnum;
11 16 import cn.iocoder.dashboard.modules.system.service.auth.SysAuthService;
12 17 import cn.iocoder.dashboard.modules.system.service.auth.SysTokenService;
  18 +import cn.iocoder.dashboard.modules.system.service.common.SysCaptchaService;
  19 +import cn.iocoder.dashboard.modules.system.service.logger.SysLoginLogService;
13 20 import cn.iocoder.dashboard.modules.system.service.permission.SysPermissionService;
14 21 import cn.iocoder.dashboard.modules.system.service.user.SysUserService;
15 22 import cn.iocoder.dashboard.util.date.DateUtils;
  23 +import cn.iocoder.dashboard.util.servlet.ServletUtils;
16 24 import io.jsonwebtoken.Claims;
17 25 import io.jsonwebtoken.JwtException;
18 26 import lombok.extern.slf4j.Slf4j;
... ... @@ -55,6 +63,10 @@ public class SysAuthServiceImpl implements SysAuthService {
55 63 private SysUserService userService;
56 64 @Resource
57 65 private SysPermissionService permissionService;
  66 + @Resource
  67 + private SysCaptchaService captchaService;
  68 + @Resource
  69 + private SysLoginLogService loginLogService;
58 70  
59 71 @Resource
60 72 private SysLoginUserRedisDAO loginUserRedisDAO;
... ... @@ -87,7 +99,7 @@ public class SysAuthServiceImpl implements SysAuthService {
87 99 @Override
88 100 public String login(String username, String password, String captchaUUID, String captchaCode) {
89 101 // 判断验证码是否正确
90   - this.verifyCaptcha(captchaUUID, captchaCode);
  102 + this.verifyCaptcha(username, captchaUUID, captchaCode);
91 103  
92 104 // 使用账号密码,进行登陆。
93 105 LoginUser loginUser = this.login0(username, password);
... ... @@ -102,18 +114,20 @@ public class SysAuthServiceImpl implements SysAuthService {
102 114 return tokenService.createToken(sessionId);
103 115 }
104 116  
105   - private void verifyCaptcha(String captchaUUID, String captchaCode) {
106   - // String verifyKey = Constants.CAPTCHA_CODE_KEY + captchaUUID;
107   -// String captcha = redisCache.getCacheObject(verifyKey);
108   -// redisCache.deleteObject(verifyKey);
109   -// if (captcha == null) {
110   -// AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.expire")));
111   -// throw new CaptchaExpireException();
112   -// }
113   -// if (!code.equalsIgnoreCase(captcha)) {
114   -// AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.error")));
115   -// throw new CaptchaException();
116   -// }
  117 + private void verifyCaptcha(String username, String captchaUUID, String captchaCode) {
  118 + String code = captchaService.getCaptchaCode(captchaUUID);
  119 + // 验证码不存在
  120 + if (code == null) {
  121 + this.createLoginLog(username, SysLoginResultEnum.CAPTCHA_NOT_FOUND);
  122 + throw ServiceExceptionUtil.exception(AUTH_LOGIN_CAPTCHA_NOT_FOUND);
  123 + }
  124 + // 验证码不正确
  125 + if (!code.equals(captchaCode)) {
  126 + this.createLoginLog(username, SysLoginResultEnum.CAPTCHA_CODE_ERROR);
  127 + throw ServiceExceptionUtil.exception(AUTH_LOGIN_CAPTCHA_CODE_ERROR);
  128 + }
  129 + // 正确,所以要删除下验证码
  130 + captchaService.deleteCaptchaCode(captchaUUID);
117 131 }
118 132  
119 133 private LoginUser login0(String username, String password) {
... ... @@ -124,22 +138,33 @@ public class SysAuthServiceImpl implements SysAuthService {
124 138 // 在其内部,会调用到 loadUserByUsername 方法,获取 User 信息
125 139 authentication = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(username, password));
126 140 } catch (BadCredentialsException badCredentialsException) {
127   - // TODO 日志优化
128   -// AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.password.not.match")));
  141 + this.createLoginLog(username, SysLoginResultEnum.BAD_CREDENTIALS);
129 142 throw exception(AUTH_LOGIN_BAD_CREDENTIALS);
130 143 } catch (DisabledException disabledException) {
131   - // TODO 日志优化
  144 + this.createLoginLog(username, SysLoginResultEnum.USER_DISABLED);
132 145 throw exception(AUTH_LOGIN_USER_DISABLED);
133 146 } catch (AuthenticationException authenticationException) {
134   - // TODO 日志优化
  147 + log.error("[login0][username({}) 发生未知异常]", username, authenticationException);
  148 + this.createLoginLog(username, SysLoginResultEnum.UNKNOWN_ERROR);
135 149 throw exception(AUTH_LOGIN_FAIL_UNKNOWN);
136 150 }
137   - // TODO 需要优化
138   -// AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success")));
  151 + // 登陆成功
139 152 Assert.notNull(authentication.getPrincipal(), "Principal 不会为空");
  153 + this.createLoginLog(username, SysLoginResultEnum.SUCCESS);
140 154 return (LoginUser) authentication.getPrincipal();
141 155 }
142 156  
  157 + private void createLoginLog(String username, SysLoginResultEnum loginResult) {
  158 + SysLoginLogCreateReqVO reqVO = new SysLoginLogCreateReqVO();
  159 + reqVO.setLogType(SysLoginLogTypeEnum.LOGIN.getType());
  160 + reqVO.setTraceId(TracerUtils.getTraceId());
  161 + reqVO.setUsername(username);
  162 + reqVO.setUserAgent(ServletUtils.getUserAgent());
  163 + reqVO.setUserIp(ServletUtils.getClientIP());
  164 + reqVO.setResult(loginResult.getResult());
  165 + loginLogService.createLoginLog(reqVO);
  166 + }
  167 +
143 168 /**
144 169 * 获得 User 拥有的角色编号数组
145 170 *
... ...
src/main/java/cn/iocoder/dashboard/modules/system/service/common/SysCaptchaService.java
... ... @@ -7,6 +7,26 @@ import cn.iocoder.dashboard.modules.system.controller.common.vo.SysCaptchaImageR
7 7 */
8 8 public interface SysCaptchaService {
9 9  
  10 + /**
  11 + * 获得验证码图片
  12 + *
  13 + * @return 验证码图片
  14 + */
10 15 SysCaptchaImageRespVO getCaptchaImage();
11 16  
  17 + /**
  18 + * 获得 uuid 对应的验证码
  19 + *
  20 + * @param uuid 验证码编号
  21 + * @return 验证码
  22 + */
  23 + String getCaptchaCode(String uuid);
  24 +
  25 + /**
  26 + * 删除 uuid 对应的验证码
  27 + *
  28 + * @param uuid 验证码编号
  29 + */
  30 + void deleteCaptchaCode(String uuid);
  31 +
12 32 }
... ...
src/main/java/cn/iocoder/dashboard/modules/system/service/common/impl/SysCaptchaServiceImpl.java
... ... @@ -35,4 +35,14 @@ public class SysCaptchaServiceImpl implements SysCaptchaService {
35 35 return SysCaptchaConvert.INSTANCE.convert(uuid, captcha);
36 36 }
37 37  
  38 + @Override
  39 + public String getCaptchaCode(String uuid) {
  40 + return captchaRedisDAO.get(uuid);
  41 + }
  42 +
  43 + @Override
  44 + public void deleteCaptchaCode(String uuid) {
  45 + captchaRedisDAO.delete(uuid);
  46 + }
  47 +
38 48 }
... ...
src/main/java/cn/iocoder/dashboard/modules/system/service/logger/SysLoginLogService.java 0 → 100644
  1 +package cn.iocoder.dashboard.modules.system.service.logger;
  2 +
  3 +import cn.iocoder.dashboard.modules.system.controller.logger.vo.loginlog.SysLoginLogCreateReqVO;
  4 +
  5 +/**
  6 + * 登陆日志 Service 接口
  7 + */
  8 +public interface SysLoginLogService {
  9 +
  10 + /**
  11 + * 创建登陆日志
  12 + *
  13 + * @param reqVO 日志信息
  14 + */
  15 + void createLoginLog(SysLoginLogCreateReqVO reqVO);
  16 +
  17 +}
... ...
src/main/java/cn/iocoder/dashboard/modules/system/service/logger/impl/SysLoginLogServiceImpl.java 0 → 100644
  1 +package cn.iocoder.dashboard.modules.system.service.logger.impl;
  2 +
  3 +import cn.iocoder.dashboard.modules.system.controller.logger.vo.loginlog.SysLoginLogCreateReqVO;
  4 +import cn.iocoder.dashboard.modules.system.convert.logger.SysLoginLogConvert;
  5 +import cn.iocoder.dashboard.modules.system.dal.mysql.dao.logger.SysLoginLogMapper;
  6 +import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.logger.SysLoginLogDO;
  7 +import cn.iocoder.dashboard.modules.system.service.logger.SysLoginLogService;
  8 +import org.springframework.stereotype.Service;
  9 +
  10 +import javax.annotation.Resource;
  11 +
  12 +/**
  13 + * 登陆日志 Service 实现
  14 + */
  15 +@Service
  16 +public class SysLoginLogServiceImpl implements SysLoginLogService {
  17 +
  18 + @Resource
  19 + private SysLoginLogMapper loginLogMapper;
  20 +
  21 + @Override
  22 + public void createLoginLog(SysLoginLogCreateReqVO reqVO) {
  23 + SysLoginLogDO loginLog = SysLoginLogConvert.INSTANCE.convert(reqVO);
  24 + loginLogMapper.insert(loginLog);
  25 + }
  26 +
  27 +}
... ...
src/main/java/cn/iocoder/dashboard/util/servlet/ServletUtils.java
... ... @@ -4,6 +4,9 @@ import cn.hutool.core.io.IoUtil;
4 4 import cn.hutool.extra.servlet.ServletUtil;
5 5 import com.alibaba.fastjson.JSON;
6 6 import org.springframework.http.MediaType;
  7 +import org.springframework.web.context.request.RequestAttributes;
  8 +import org.springframework.web.context.request.RequestContextHolder;
  9 +import org.springframework.web.context.request.ServletRequestAttributes;
7 10  
8 11 import javax.servlet.http.HttpServletRequest;
9 12 import javax.servlet.http.HttpServletResponse;
... ... @@ -54,4 +57,33 @@ public class ServletUtils {
54 57 return ua != null ? ua : "";
55 58 }
56 59  
  60 + /**
  61 + * 获得请求
  62 + *
  63 + * @return HttpServletRequest
  64 + */
  65 + public static HttpServletRequest getRequest() {
  66 + RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
  67 + if (!(requestAttributes instanceof ServletRequestAttributes)) {
  68 + return null;
  69 + }
  70 + return ((ServletRequestAttributes) requestAttributes).getRequest();
  71 + }
  72 +
  73 + public static String getUserAgent() {
  74 + HttpServletRequest request = getRequest();
  75 + if (request == null) {
  76 + return null;
  77 + }
  78 + return getUserAgent(request);
  79 + }
  80 +
  81 + public static String getClientIP() {
  82 + HttpServletRequest request = getRequest();
  83 + if (request == null) {
  84 + return null;
  85 + }
  86 + return ServletUtil.getClientIP(request);
  87 + }
  88 +
57 89 }
... ...