App用户登陆 java后台处理和用户权限验证(AOP)

用户登录java后台的处理,主要是通过session来判断。本人属于新手,最开始也是模仿着自己的师傅来copy代码,接下来我就先使用师傅教给我的方法,如下:

一.App每次请求接口时都需传入一个String类型的sessionId,进行一系列的判断,期间使用了很多封装好的工具类。下面是其中的一个测试接口。

/*
* app登录验证
*/
  @ResponseBody
  @RequestMapping(value = "/api/get", method = RequestMethod.GET)
  public Object get(HttpServletRequest request,@RequestParam("sessionId")String sessionId){
      //判断用户的session是否正常
      //获取session
      if (sessionId == null || sessionId .equals("")) {
      	  //Resoponse 是一个工具类          return new Response(Status.ERROR, "sessionId不能为空");      }      //MySessionContext 是一个工具类
      MySessionContext myc = MySessionContext.getInstance();
      HttpSession httpSession = myc.getSession(sessionId);
      if (httpSession == null) {
          return new Response(14, "sessionId失效");
      }
      //登录时,用户信息已经保存在session中,在session中取出用户信息(ActionUtil是一个工具类)
      User obj = ActionUtil.getCurrentUser(httpSession);
      if (obj == null) {
          return new Response(14, "sessionId失效");
      }
      return new Response(0, "测试成功",obj);
  }

经过测试,登录成功后,测试结果为:

{"status": 0,
  "body": {
    "id": "54C7861CBC2C47A08E75D1EE5887E00F"
  },
  "message": "测试成功",
  "currentPage": 0,
  "totalPage": 0,
  "totalRow": 0}

表示通过登录验证,接下来就可以做其它的操作了。以下是本次所需要的一些工具类:

MySessionContext.java   //开启这个SessionContext需要自定义一个SessionListener并在web.xml里面声明,方可进行测试

import javax.servlet.http.HttpSession;
import java.util.HashMap;

/**
 * 建立一个自己的SessionContext
 * 并且自定义一个Session监听即SessionListener
 */
public class MySessionContext {
    private static MySessionContext instance;
    private HashMap mymap;

    private MySessionContext() {
        mymap = new HashMap();
    }

    public static MySessionContext getInstance() {
        if (instance == null) {
            instance = new MySessionContext();
        }
        return instance;
    }

    public synchronized void AddSession(HttpSession session) {
        if (session != null) {
            mymap.put(session.getId(), session);
        }
    }

    public synchronized void DelSession(HttpSession session) {
        if (session != null) {
            mymap.remove(session.getId());
        }
    }

    public synchronized HttpSession getSession(String session_id) {
        if (session_id == null) return null;
        return (HttpSession) mymap.get(session_id);
    }

}

SessionListener.java


import javax.servlet.http.HttpSessionListener;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSession;
import java.util.HashMap;
import java.util.Map;

/**
 * 新建一个Session监听
 */
public class SessionListener implements HttpSessionListener {
    private  MySessionContext myc = MySessionContext.getInstance();

    public void sessionCreated(HttpSessionEvent httpSessionEvent) {
        myc.AddSession(httpSessionEvent.getSession());
    }

    public void sessionDestroyed(HttpSessionEvent httpSessionEvent) {
        HttpSession session = httpSessionEvent.getSession();
        myc.DelSession(session);
    }
}

web.xml

<!-- 配置自己的session监听 -->
<listener>
    <listener-class>com.aqb.cn.utils.getSession.SessionListener</listener-class>
</listener>

ActionUtil.java

import com.aqb.cn.bean.Admin;
import com.aqb.cn.bean.User;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.io.File;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.HashMap;
import java.util.Map;

public class ActionUtil {
   public static final SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
   public static final SimpleDateFormat simpleDateFormat1 = new SimpleDateFormat("yyyyMMdd");
   public static final SimpleDateFormat simpleDateFormat2 = new SimpleDateFormat("yy");
   public static final DecimalFormat decimalFormat = new DecimalFormat("0000");
   public static final DecimalFormat decimalFormat1 = new DecimalFormat("0.00");

   public final static String RECEIPT_SAVE_PATH = File.separator+"upload"+File.separator+"Receipt";
   
   public static final String SESSION_USER = "SESSION_USER";
   public static final String SESSION_USER_LOGOUT = "TK_USER_LOGOUT";// 用户登出
   public static final String SESSION_USER_ACTIVATION_KEY = "TK_USER_ACTIVATION_KEY";
   public static final String SESSION_USER_RESETPASSWORD_KEY = "TK_USER_RESETPASSWORD_KEY";

   public static final String SESSION_Admin = "TK_Admin";
   public static final String SESSION_Admin_LOGOUT = "TK_Admin_LOGOUT";
   public static final String SESSION_Admin_ACTIVATION_KEY = "TK_Admin_ACTIVATION_KEY";
   public static final String SESSION_Admin_RESETPASSWORD_KEY = "TK_Admin_RESETPASSWORD_KEY";

   public static final String SESSION_Doctor = "TK_Doctor";
   public static final String SESSION_Doctor_LOGOUT = "TK_Doctor_LOGOUT";
   public static final String SESSION_Doctor_ACTIVATION_KEY = "TK_Doctor_ACTIVATION_KEY";
   public static final String SESSION_Doctor_RESETPASSWORD_KEY = "TK_Doctor_RESETPASSWORD_KEY";

   public static final String SESSION_FINANCINGCOMPANY = "TK_FINANCINGCOMPANY";
   public static final String SESSION_FINANCINGCOMPANY_LOGOUT = "TK_FINANCINGCOMPANY_LOGOUT";
   public static final String SESSION_FINANCINGCOMPANY_ACTIVATION_KEY = "TK_FINANCINGCOMPANY_ACTIVATION_KEY";
   public static final String SESSION_FINANCINGCOMPANY_RESETPASSWORD_KEY = "TK_FINANCINGCOMPANY_RESETPASSWORD_KEY";

   public static final String CONTRACT_NUM = "CONTRACT_NUM";

   public static final Map<String,String> fileNameMap = new HashMap();
   public static User getCurrentUser(HttpServletRequest request) {
      User user = (User) request.getSession().getAttribute(SESSION_USER);
      return user;
   }
   public static User getCurrentUser(HttpSession httpSession) {
      Object obj = httpSession.getAttribute(SESSION_USER);
      if(obj == null){
         return null;
      }
      return (User)obj;
   }

   public static void setCurrentUser(HttpServletRequest request, User user) {
      HttpSession session = request.getSession();
      session.setAttribute(SESSION_USER, user);
      session.setAttribute(SESSION_USER_LOGOUT, false);
   }

   public static HttpSession getUserSession(HttpServletRequest request, User user) {
      HttpSession session = request.getSession();
      session.setAttribute(SESSION_USER, user);
      session.setAttribute(SESSION_USER_LOGOUT, false);
      return session;
   }

   public static Admin getCurrentAdmin(HttpServletRequest request) {
      Admin admin = (Admin) request.getSession().getAttribute(SESSION_Admin);
      return admin;
   }

   public static Admin getCurrentAdmin(HttpSession httpSession) {
      Object obj = httpSession.getAttribute(SESSION_Admin);
      if(obj == null){
         return null;
      }
      return (Admin)obj;
   }

   public static void setCurrentAdmin(HttpServletRequest request, Admin Admin) {
      HttpSession session = request.getSession();
      session.setAttribute(SESSION_Admin, Admin);
      session.setAttribute(SESSION_Admin_LOGOUT, false);
   }
   
   public static void removeCurrentUser(HttpServletRequest request) {
      HttpSession session = request.getSession();
      session.removeAttribute(SESSION_USER);
      session.setAttribute(SESSION_USER_LOGOUT, true);
   }

   public static void removeCurrentAdmin(HttpServletRequest request) {
      HttpSession session = request.getSession();
      session.removeAttribute(SESSION_Admin);
      session.setAttribute(SESSION_Admin_LOGOUT, true);
   }

   public static void removeCurrentDoctor(HttpServletRequest request) {
      HttpSession session = request.getSession();
      session.removeAttribute(SESSION_Doctor);
      session.setAttribute(SESSION_Doctor_LOGOUT, true);
   }

   public static void removeCurrentManufacturer(HttpServletRequest request) {
      HttpSession session = request.getSession();
      session.removeAttribute(SESSION_Doctor);
      session.setAttribute(SESSION_Doctor_LOGOUT, true);
   }

   public static void removeCurrentOperate(HttpServletRequest request) {
      HttpSession session = request.getSession();
      session.removeAttribute(SESSION_FINANCINGCOMPANY);
      session.setAttribute(SESSION_FINANCINGCOMPANY_LOGOUT, true);
   }
   
   public static boolean getLogout(HttpServletRequest request) {
      Object r = request.getSession().getAttribute(SESSION_USER_LOGOUT);
        return r != null && (Boolean) r;
   }

   public static boolean getLogoutAdmin(HttpServletRequest request) {
      Object r = request.getSession().getAttribute(SESSION_Admin_LOGOUT);
      return r != null && (Boolean) r;
   }

   public static void setActivationKey(HttpServletRequest request, String key) {
      request.getSession().setAttribute(SESSION_USER_ACTIVATION_KEY, key);
   }

   public static void setActivationKeyAdmin(HttpServletRequest request, String key) {
      request.getSession().setAttribute(SESSION_Admin_ACTIVATION_KEY, key);
   }

   public static String getActivationKey(HttpServletRequest request) {
      String key = (String) request.getSession().getAttribute(
            SESSION_USER_ACTIVATION_KEY);
      return key;
   }

   public static String getActivationKeyAdmin(HttpServletRequest request) {
      String key = (String) request.getSession().getAttribute(
            SESSION_Admin_ACTIVATION_KEY);
      return key;
   }

   public static void removeActivationKey(HttpServletRequest request) {
      request.getSession().removeAttribute(SESSION_USER_ACTIVATION_KEY);
   }

   public static void removeActivationKeyAdmin(HttpServletRequest request) {
      request.getSession().removeAttribute(SESSION_Admin_ACTIVATION_KEY);
   }

   public static void setResetPasswordKey(HttpServletRequest request,
         String key) {
      request.getSession().setAttribute(SESSION_USER_RESETPASSWORD_KEY, key);
   }

   public static void setResetPasswordKeyAdmin(HttpServletRequest request,
                                 String key) {
      request.getSession().setAttribute(SESSION_Admin_RESETPASSWORD_KEY, key);
   }

   public static String getResetPasswordKey(HttpServletRequest request) {
      String key = (String) request.getSession().getAttribute(
            SESSION_USER_RESETPASSWORD_KEY);
      return key;
   }

   public static String getResetPasswordKeyAdmin(HttpServletRequest request) {
      String key = (String) request.getSession().getAttribute(
            SESSION_Admin_RESETPASSWORD_KEY);
      return key;
   }

   public static void removeResetPasswordKey(HttpServletRequest request) {
      request.getSession().removeAttribute(SESSION_USER_RESETPASSWORD_KEY);
   }

   public static void removeResetPasswordKeyAdmin(HttpServletRequest request) {
      request.getSession().removeAttribute(SESSION_Admin_RESETPASSWORD_KEY);
   }
}



Response.java

/**
 * 对返回值进行封装,方便查看请求接口是否成功
 * 
 */
public class Response {

   protected int status;// 状态码
   protected Object body;// JSON格式的值,里面放返回给前端的具体数据
   protected String message;// 状态描述
   protected long currentPage;//当前页
   protected long totalPage;//总页数
   protected long totalRow;//总行数
   
   public Response() {
   }

   public Response(int status) {
      this.status = status;
   }

   public Response(int status, String message) {
      this(status);
      this.message = message;
   }

   public Response(int status, Object body) {
      this(status);
      this.body = body;
   }

   public Response(int status, String message, Object body) {
      this(status, message);
      this.body = body;
   }
   public Response(int status,  long totalRow, Object body) {
      this.status = status;
      this.totalRow = totalRow;
      this.body = body;
   }
   
   public Response(short status, long totalRow, long totalPage, Object body,long currentPage) {
      this.status = status;
      this.totalRow = totalRow;
      this.totalPage = totalPage;
      this.body = body;
      this.currentPage = currentPage;
   }

   public Response(short status, long totalRow, long totalPage, Object body) {

      this.status = status;
      this.totalRow = totalRow;
      this.totalPage = totalPage;
      this.body = body;
      //this.currentPage = currentPage;
   }

   public long getTotalRow() {
      return totalRow;
   }

   public void setTotalRow(long totalRow) {
      this.totalRow = totalRow;
   }

   public long getCurrentPage() {
      return currentPage;
   }

   public void setCurrentPage(long currentPage) {
      this.currentPage = currentPage;
   }

   public long getTotalPage() {
      return totalPage;
   }

   public void setTotalPage(long totalPage) {
      this.totalPage = totalPage;
   }

   public int getStatus() {
      return status;
   }

   public void setStatus(int status) {
      this.status = status;
   }

   public Object getBody() {
      return body;
   }

   public void setBody(Object body) {
      this.body = body;
   }

   public String getMessage() {
      return message;
   }

   public void setMessage(String message) {
      this.message = message;
   }
}



二。首先面对这种,根据经验,常规解决方案就是过滤器,拦截器,若是在需求安排上登陆和权限验证这些放在前面的话,只要让后期功能的url有一定规律,过滤器或拦截器的使用简直屡试不爽。但是我现在面对的是前期没有任何设计和规范的url,所以使用过滤器或者拦截器是我不愿意面对的。

    除了以上常规解决方案,spring AOP正好成了解决这类问题的利器,利用面相切面编程对所有需要权限验证的method做一个前置通知,但是由于url,类名或者方法没有规律,于是我想到了自定义注解(annotation),对所有加上自定义注解的method做权限验证。

1.想到使用spring aop,那首先第一步就是在spring配置文件中开启aop,并注入自定义的切面类


<!--启动对@AspectJ注解的支持,并注入自定义的切面类-->
<aop:aspectj-autoproxy proxy-target-class="true"/>
<bean class="com.aqb.cn.aspectj.UserLoginAspectj" name="userLoginAspectj"/>


2.其次我们先定义一个自定义annotation



/**
 * 用户登录验证
 */
public @interface UserLogin {

}

3.自定义的一个切面类,UserLoginAspectj.java。完成以后,我们只需在每个接口实现@

UserLogin注解即可完成登录验证

import com.aqb.cn.bean.User;
import com.aqb.cn.common.ActionUtil;
import com.aqb.cn.common.Response;
import com.aqb.cn.common.Status;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;

@Aspect
public class UserLoginAspectj {
    private Log logger = LogFactory.getLog(UserLoginAspectj.class);

    @Resource(name="sessionOutTimeResponse")  //在Spring-MVC文件中有注解,可以采用这种配置文件的方式
        Response sessionOutTimeResponse;
    @Resource(name="sessionRepeatResponse")  //在Spring-MVC文件中有注解
        Response sessionRepeatResponse;
    @Resource(name="sessionQxResponse")  //在Spring-MVC文件中有注解
            Response sessionQxResponse;

    @Around("@annotation(com.aqb.cn.annotation.UserLogin)")//使用我们自定义的注解,Around 环绕的方式
     public Object checkUserAuthorized(ProceedingJoinPoint point) throws Throwable{
        try{
            HttpServletRequest request=(HttpServletRequest) point.getArgs()[0];
            User user = ActionUtil.getCurrentUser(request);
            if (user != null){
                return point.proceed();
            }
        }catch(Exception e){
            e.printStackTrace();
            return new Response(Status.ERROR,"系统错误");
        }
        return sessionOutTimeResponse;
    }
    
}



4.此时上面的测试接口就可以大大简化,如下:


/*
* app登录验证
*/
  @UserLogin
  @ResponseBody
  @RequestMapping(value = "/api/get", method = RequestMethod.GET)
  public Object get(HttpServletRequest request){

      User user = ActionUtil.getCurrentUser(request);
      if (user == null) {
          return new Response(14, "sessionId失效");
      }
      return new Response(0, "测试成功",user);
  }

如果用户先登录,那么测试结果和上面的接口测试结果是一样的,如果没有登录,则登录验证失败。

所以,总结起来,使用Spring AOP切面,主要是我们需要在spring-mvc.xml文件开启aop,并注入自定义的切面类,而切面类也包含了自定义的UserLogin的注解,然后就可以使用自定义的UserLogin注解来进行登录验证了,即在接口方法加上"@UserLogin"即可完成登录验证,这样就大大缩减了代码量,在每个需要登录验证的接口方法加上"@UserLogin"即可,相比于spring的拦截器(Interceptor),在web.xml自定义的过滤器(Filter)更加方便。