每个页面都要写检查是否登录的代码,很麻烦,因此定义一个AllowAnonymous的自定义Annotation,所有标记AllowAnonymous的不需要登录状态,其他都要做登录检查 自定义一个Annotation:
@Target(value=ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME) public
@interface HasPermission { public String value(); } 这叫做AOP(面向切面编程),action不用再写权限检查的代码了。 BasicServlet中检查是否有权限:首先必须要检查是否登录,调用DAO的CheckPermission方法 BasicServlet中还可以记录日志
1.创建自定义Annotation
(1)AllowAnonymous(检查是否需要登录)
package com.zsz.admin.servlet;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
//表示被标注的方法允许匿名(不登录)访问
@Target(value=ElementType.METHOD)
@Retention(value=RetentionPolicy.RUNTIME)
public @interface AllowAnonymous {
}
(2)HasPermission(检查角色是否有权限)
package com.zsz.admin.servlet;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface HasPermission {
public String value();//如果自定义注解中,属性的名字是value,那么赋值的时候可以省略value=
}
2.在需要匿名访问的方法上加上标识
(1)
@AllowAnonymous
public void verifyCode(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String code = VerifyCodeUtils.generateVerifyCode(4);
req.getSession().setAttribute("verifyCode", code);
resp.setContentType("image/jpeg");
VerifyCodeUtils.outputImage(100, 50, resp.getOutputStream(), code);
}
(2)
@HasPermission("AdminUser.Query")
public void list(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
AdminUserService service = new AdminUserService();
AdminUserDTO[] adminUsers = service.getAll();
req.setAttribute("adminUsers", adminUsers);
req.getRequestDispatcher("/WEB-INF/adminUser/adminUserList.jsp").forward(req, resp);
}
3.调用方法判断是否匿名,如果是则可以访问,否则提示未登录
package com.zsz.admin.servlet;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.zsz.admin.utils.AdminUtils;
import com.zsz.service.AdminUserService;
import com.zsz.tools.AjaxResult;
public class BaseServlet extends HttpServlet {
private static final Logger logger = LogManager.getLogger(BaseServlet.class);
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String action = req.getParameter("action");
if (StringUtils.isEmpty(action)) {
AdminUtils.showError(req, resp, "action is empty!");
//resp.getWriter().print("action is empty!");
logger.warn("action为空");
return;
}
Class clz = this.getClass();// Class是子类的Class,不是BaseServlet
// 约定方法的名字就是 action的名字(req,resp)
try {
Method methodAction = clz.getMethod(action, HttpServletRequest.class, HttpServletResponse.class);
//AOP思想:
//获得方法上标注的“是否允许匿名访问”AllowAnonymous
AllowAnonymous allowAnonymous = methodAction.getAnnotation(AllowAnonymous.class);
if(allowAnonymous==null)//如果为null,就说明方法没有标注AllowAnonymous,则需要检查登录状态
{
//统一检查用户是否有登录,如果没有登录,则直接不执行methodAction.invoke
Long userId = AdminUtils.getAdminUserId(req);
if(userId==null)
{
String ctxPath = req.getContextPath();
// target='_top'避免链接在iframe中打开,而是再顶层浏览器窗口中打开
AdminUtils.showError(req, resp, "未登录<a target='_top' href='"+ctxPath+"/Index?action=login'>点此登录</a>");
return;//!!!!!
}
//已经登录
//统一的权限控制,需要进行权限控制的方法标注HasPermission即可
//获得方法上标注的HasPermission
HasPermission hasPermission = methodAction.getAnnotation(HasPermission.class);
if(hasPermission!=null)//如果方法上标注了HasPermission,则要检查当前用户是否有相应权限
{
AdminUserService adminUserService = new AdminUserService();
boolean isOK = adminUserService.hasPermission(userId, hasPermission.value());
if(!isOK)
{
AdminUtils.showError(req, resp, "无权访问!");
return;//!!!!!
}
}
}
// 拿到了 public void index(HttpServletRequest req, HttpServletResponse
// resp) 方法
methodAction.invoke(this, req, resp); // 调用方法
} catch (NoSuchMethodException | SecurityException e) {
//resp.getWriter().print("cannot invoke action method:" + action);
AdminUtils.showError(req, resp, "cannot invoke action method:" + action);
logger.warn("找不到名字为"+action+"的方法",e);
} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
//resp.getWriter().print("invoke method " + action + " error");
AdminUtils.showError(req, resp, "invoke method " + action + " error");
logger.warn("调用名字为"+action+"的方法失败",e);
}
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doGet(req, resp);
}
protected void writeJson(HttpServletResponse resp,AjaxResult ajaxResult) throws IOException
{
resp.setContentType("application/json;charset=UTF-8");
resp.getWriter().print(ajaxResult.toJson());
}
}