上线的项目,不可避免的会遇见用户提出的bug,这时候我们可能需要去用户的页面重现用户所说的Bug,为了安全,最好进入用户页面的时候不能修改用户的数据,只能查看。
对于上述需求实现的方法有多种:
1:根据ajax请求方式来进行拦截,如果ajax请求方式不是get请求,则在filter或者aop中拦截掉,这种方法实现起来最简单,能较好的在分布式系统发挥工作,但是要求接口必须是restful风格。
2:在操作dao之前进行拦截,在进行数据库操作之前如果检测到当前的用户只允许查看,则抛异常进行拦截,下面讲述此种方式:
大致过程:
(1)编写mybatis拦截器拦截所有的增删改sql。
(2):若是访客身份登录用户账户则分配一个cookie用来表明当前用户是访客身份,以便于mybatis拦截器判断,也可以将此标志放在session中,在mybatis拦截器中通过sessionId从session中判断用户是否访客身份。
(3):在异常处理器中捕获拦截器拦截后抛出的异常,并返回提示给客户端。
具体实现:
(1)首先编写mybatis拦截器以便于拦截所有的修改sql,代码如下:
package cn.lll.iic.ssp.mgr.common;
import cn.lll.framework.exception.IllegalUpdateException;
import cn.lll.framework.util.ToolUtil;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.plugin.*;
import java.util.Properties;
/**
* @time:2020/9/28
* @function:拦截sql更新操作
*/
@Intercepts({
@Signature(type = Executor.class, method = "update", args = {MappedStatement.class, Object.class})
})
public class MybatisEventInterceptor implements Interceptor {
@Override
public Object intercept(Invocation invocation) throws Throwable {
//判断登录来源
String origin = ToolUtil.getCookieValue("origin");
System.out.println(origin);
if ("admin".equals(origin)){
throw new IllegalUpdateException("当前登录身份不允许更新");
}
return invocation.proceed();
}
@Override
public Object plugin(Object target) {
return Plugin.wrap(target, this);
}
@Override
public void setProperties(Properties properties) {}
}
获取cookie方法对应代码:
/**
* @description:从当前线程上线文获取请求参数,必须在spring web项目下使用
* @param paramName 参数名
* @return java.lang.String
*/
public static String getCurrentUsername(String paramName){
ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = servletRequestAttributes.getRequest();
return request.getParameter(paramName);
}
//从当前请求中获取指定cookie的值,必须在spring web项目下使用
public static String getCookieValue(String key){
ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = servletRequestAttributes.getRequest();
Cookie[] cookies = request.getCookies();
if (cookies == null) return "";
for (Cookie cookie : cookies) {
if ( Objects.equals(key, cookie.getName()) ){
return cookie.getValue();
}
}
return "";
}
应用启动加载拦截器:
@Configuration
public class SspCfg {
@Autowired
private List<SqlSessionFactory> sqlSessionFactoryList;
//注入的bean执行的初始化方法,执行一次
@PostConstruct
public void addMySqlInterceptor() {
MybatisEventInterceptor interceptor = new MybatisEventInterceptor();
//拦截sql更新操作
for (SqlSessionFactory sqlSessionFactory : sqlSessionFactoryList) {
sqlSessionFactory.getConfiguration().addInterceptor(interceptor);
}
}
}
(2):编写访客登录接口,并设置cookie,登录成功后跳转到主页。
@GetMapping(path = "/login-admin")
public JsonResult adminLogin(@RequestParam(name = "username") String username, @RequestParam(name = "pwd") String adminPwd){
try {
SysUser user = iMgrLoginService.adminLogin(username, adminPwd);
this.saveSession(this.SYS_AUTH_SESSION_USERNAME, user);
//cookie注明是admin登录用户账户
Cookie flagCookie = new Cookie("origin", "admin");
flagCookie.setPath("/");
this.response.addCookie(flagCookie);
this.response.sendRedirect("/index.html");
return null;
} catch (BusException | IOException e) {
return JsonResult.createFail(e);
}
}
除此之外,在用户登录之前我们还需将新加的origin cookie删除,以免影响用户登录:
(3):处理拦截器抛出的自定义异常。
异常代码:
/**
* @time:2020/9/29
* @function:不允许的sql更新异常
*/
public class IllegalUpdateException extends RuntimeException{
public IllegalUpdateException(String message) {
super(message);
}
}
结束。