zoukankan      html  css  js  c++  java
  • 在线用户双重判断

    一、用户是否在线校验(双重保障)

    先经过注解进入全局拦截器;再通过异常处理器来处理

    方式一:通过面向切面的思想,使用注解接口来拦截,需要传递request对象,才可以获取用户信息(全局拦截器处理)

    方式二:通过全局对象(不需要传参),获取当前request对象,request对象再通过用户数据来判断用户是否在线(全局异常处理)

    1.1 控制层(获取角色和权限数据)

    /**
     * 	获取用户的角色和权限数据
     * @author HuangJingNa
     * @date 2019年12月22日 下午4:01:55
     *
     * @return
     * @throws Exception 
     */
    @PostMapping("find_role_permission")
    @CheckRoles({"role:student"})
    @CheckPerssions({"permission:study", "permission:sleep"})
    public Object findRolePerssion() throws Exception {
    	return userService.findRolePerssion();
    }
    

    1.2 进入全局拦截器(注解)

    package cn.kooun.core.interceptor;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.web.method.HandlerMethod;
    import org.springframework.web.servlet.HandlerInterceptor;
    
    import cn.kooun.service.UserService;
    
    /**
     * 	全局拦截器
     * @author HuangJingNa
     * @date 2019年12月22日 下午4:40:45
     *
     */
    public class GlobalInterceptor implements HandlerInterceptor{
    	@Autowired
    	private UserService userService;
    	
    	@Override
    	public boolean preHandle(
    			HttpServletRequest request, 
    			HttpServletResponse response, 
    			Object handler) throws Exception {
    		if(handler instanceof HandlerMethod) {
    			HandlerMethod handlerMethod = (HandlerMethod) handler;
    			return baseHandler(request, response, handlerMethod);
    		}
    		return true;
    	}
    	private boolean baseHandler(
    			HttpServletRequest request, 
    			HttpServletResponse response, 
    			HandlerMethod handlerMethod) {
    		boolean flag = true;
    		flag = userService.checkOnline(request, response, handlerMethod);
    		if(!flag) {
    			return flag;
    		}
    		flag = userService.checkRoles(request, response, handlerMethod);
    		if(!flag) {
    			return flag;
    		}
    		flag = userService.checkPerssions(request, response, handlerMethod);
    		if(!flag) {
    			return flag;
    		}
    		return flag;
    	}
    }
    

    不管是否有该注解,都会进入全局拦截器中

    1.3 service层CheckOnline()中需要将登录时封装的用户对象设置在request域中

    	 /** 	
    	  *    校验是否在线
    	 * @author HuangJingNa
    	 * @date 2019年12月22日 下午4:48:13
    	 *
    	 * @param request
    	 * @param response
    	 * @param handlerMethod
    	 * @return
    	 */
    	public boolean checkOnline(
    			HttpServletRequest request, 
    			HttpServletResponse response, 
    			HandlerMethod handlerMethod) {
    		//获取方法上的注解,判断是否要进行校验
    		NotCheckOnline notCheckOnline = handlerMethod.getMethodAnnotation(NotCheckOnline.class);
    		if(notCheckOnline != null) {
    			//放行,不进行校验
    			return true;
    		}
    		
    		//获取在线用户
    		Object user = RequestUtils.getUserLogin(request, response, redisService);
    		if(user == null) {
    			ResponseUtils.returnJson(
    					response, 
    					ResultUtils.error("登录失效,请重新登录~", Result.JUMP_LOGIN));
    			return false;
    		}
    		//设置request.setAttribute(),方便全局校验获取用户数据
    		request.setAttribute(Dict.USER, user);
    		
    		return true;
    	}
    
    请求类RequestUtils
    package cn.kooun.common.request;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    import org.springframework.util.StringUtils;
    
    import cn.kooun.common.redis.RedisService;
    import cn.kooun.pojo.info.Dict;
    
    /**
     * 	请求工具类
     * @author HuangJingNa
     * @date 2019年12月22日 下午4:52:10
     *
     */
    public class RequestUtils {
    	/**
    	 * 	校验用户是否在线(根据用户凭证)
    	 * @author HuangJingNa
    	 * @date 2019年12月22日 下午5:03:40
    	 *
    	 * @param request
    	 * @param response
    	 * @param redisService
    	 * @return
    	 */
    	public static Object getUserLogin(
    			HttpServletRequest request, 
    			HttpServletResponse response,
    			RedisService redisService) {
    		//登录校验
    		String userToken = request.getHeader(Dict.USER_TOKEN);
    		if(StringUtils.isEmpty(userToken)) {
    			return null;
    		}
    		//返回在线数据
    		return redisService.get(userToken);
    	}
    	
    }
    
    相应类ReponseUtils
    package cn.kooun.common.reponse;
    
    import java.io.PrintWriter;
    
    import javax.servlet.http.HttpServletResponse;
    
    import com.alibaba.fastjson.JSON;
    
    import cn.kooun.pojo.info.Dict;
    
    /**
     * 	响应工具类
     * @author HuangJingNa
     * @date 2019年12月22日 下午4:52:24
     *
     */
    public class ResponseUtils {
    	/**
    	 * response响应json数据格式
    	 * 
    	 * @author HuangJingNa
    	 * @date 2019年12月22日 下午4:52:24
    	 * @param response
    	 * @param result
    	 */
    	public static void returnJson(HttpServletResponse response, Object result) {
    		//创建json转换的类
    		PrintWriter writer = null;
    		try {
    			// 避免乱码
    			response.setCharacterEncoding(Dict.UTF8);
    			// 设置ContentType
    			response.setContentType(Dict.JSON_HEAD);
    			writer = response.getWriter();
    			writer.append(JSON.toJSONString(result));
    			writer.flush();
    		} catch (Exception e) {
    			e.printStackTrace();
    		}finally {
    			if(writer!=null) {
    				writer.close();
    			}
    		}
    	}
    }
    
    使用全局对象获取用户对象时才有值
    	 /**
    	 * 	获取用户的角色和权限数据
    	 * @author HuangJingNa
    	 * @date 2019年12月22日 下午4:03:19
    	 *
    	 * @return
    	 * @throws Exception 
    	 */
    	public Object findRolePerssion() throws Exception {
    		//使用全局对象来判断用户是否在线
    		LoginUser user = (LoginUser) SecurityUtils.getCurrentUser();
    		return packageRolesAndPermissions(user);
    	}
    	/**
    	 * 	打包角色和权限数据
    	 * @author HuangJingNa
    	 * @date 2019年12月22日 下午4:30:49
    	 *
    	 * @param user
    	 * @return
    	 */
    	private Object packageRolesAndPermissions(LoginUser user) {
    		//在线:获取权限和角色
    		List<String> roles = user.getRoles();
    		List<String> permissions = user.getPermissions();
    		Map<String, Object> result = new HashMap<String, Object>();
    		result.put("roles", roles);
    		result.put("permissions", permissions);
    		return ResultUtils.success(result);
    	}
    

    1.4 权限工具SecurityUtils

    package cn.kooun.common;
    
    import javax.servlet.http.HttpServletRequest;
    
    import org.springframework.web.context.request.RequestContextHolder;
    import org.springframework.web.context.request.ServletRequestAttributes;
    
    import cn.kooun.pojo.exception.OffLineException;
    import cn.kooun.pojo.info.Dict;
    
    /**
     * 	权限工具
     * @author HuangJingNa
     * @date 2019年12月23日 下午2:44:54
     *
     */
    public class SecurityUtils {
    	/**
    	 * 	获取当前用户
    	 * 	可以作为全局对象来获取当前request对象,
    	 * 	再使用request对象(通过用户key值)来获取用户数据,来判断用户是否登录
    	 * 	方式一:通过注解接口的方式来判断用户是否在线(根据用户凭证);全局拦截器处理
    	 * 	方式二:使用全局对象来获取request对象;全局异常处理
    	 * 	以上两个方式,双重保障
    	 * @author HuangJingNa
    	 * @date 2019年12月23日 下午2:46:39
    	 *
    	 * @return
    	 * @throws ffLineException 
    	 */
    	public static Object getCurrentUser() throws Exception {
    		HttpServletRequest request = 
    				((ServletRequestAttributes)RequestContextHolder.getRequestAttributes())
    				.getRequest();
    		Object user = request.getAttribute(Dict.USER);
    		if(user == null) {
    			throw new OffLineException("用户不在线~");
    		}
    		return user;
    	}
    }
    

    1.5 用户不在线异常处理OffLineException

    package cn.kooun.pojo.exception;
    /**
     * 	自定义异常,用户不在线抛出的异常
     * @author HuangJingNa
     * @date 2019年12月23日 下午2:55:38
     *
     */
    public class OffLineException extends Exception{
    
    	private static final long serialVersionUID = 7291020619358516087L;
    
    	public OffLineException() {
    		super();
    	}
    
    	public OffLineException(String message) {
    		super(message);
    	}
    	
    }
    

    1.6 全局拦截器处理该自定义异常

    package cn.kooun.core.exception;
    
    import javax.servlet.http.HttpServletRequest;
    
    import org.springframework.web.bind.annotation.ControllerAdvice;
    import org.springframework.web.bind.annotation.ExceptionHandler;
    import org.springframework.web.bind.annotation.ResponseBody;
    
    import cn.kooun.common.result.Result;
    import cn.kooun.common.result.ResultUtils;
    import cn.kooun.pojo.exception.OffLineException;
    
    /**
     *	全局异常处理
     * @author HuangJingNa
     * @date 2019年12月21日 下午3:46:19
     *
     */
    @ControllerAdvice//标记此类为全局异常拦截器
    public class GlobalExceptionHandler {
    	/**
    	 * 	系统异常处理,如404、500
    	 * @author HuangJingNa
    	 * @date 2019年12月21日 下午3:48:45
    	 *
    	 * @return
    	 * @throws Exception
    	 */
    	@ExceptionHandler(value = Exception.class)//监听对应的异常对象
    	@ResponseBody
    	public Object defaultErrorHandler(HttpServletRequest req, Exception e) throws Exception{
    		//控制台输出错误信息
    		e.printStackTrace();
    		if(e instanceof OffLineException) {
    			return ResultUtils.error("登录失效,请重新登录~", Result.JUMP_LOGIN);
    		}
    		return ResultUtils.error("系统繁忙,请联系管理员~");
    	}
    }
    
  • 相关阅读:
    开发趋势
    常用的meta
    meta基础
    HTTP请求方法GET和POST
    same-origin policy----wikipedia
    跨域——同源策略(译)
    DNS问答
    TCP/IP的整理
    鉴权方法
    Web攻击技术---OWASP top
  • 原文地址:https://www.cnblogs.com/nadou/p/14003920.html
Copyright © 2011-2022 走看看