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)更加方便。