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