管控用户网页登陆后才能操作其它页面方法(BasicServlet权限控制)

每个页面都要写检查是否登录的代码,很麻烦,因此定义一个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());
    }

}
 

  

猜你喜欢

转载自blog.csdn.net/pale42/article/details/88601501