自定義注解實現權限管理框架或其它功能擴充


在進行springMVC進行J2EE項目開發時,spring及第三方的如Shiro等為我們快速實現某個功能提供了注解標簽,配置和使用都及其簡單

但在某些情況下,需要根據項目需要,自定義某些功能時就會用到今天講到的自定義標簽

 

以進行簡單的權限攔截為例來進行講解

 

當某個controller中的方法,需要具有某個權限或者角色的人員才能執行時,我們分如下幾步進行自定義的權限攔截

第一步:定義注解標簽

 1 package net.zicp.xiaochangwei.web.annotation;
 2 
 3 import java.lang.annotation.Documented;
 4 import java.lang.annotation.ElementType;
 5 import java.lang.annotation.Retention;
 6 import java.lang.annotation.RetentionPolicy;
 7 import java.lang.annotation.Target;
 8 
 9 /**
10  * 
11  * @author xiaochangwei
12  * 自定義權限標簽
13  */
14 @Target(ElementType.METHOD)
15 @Retention(RetentionPolicy.RUNTIME)
16 @Documented
17 public @interface SelfPermission {
18     String value() default "";
19 }

第二步:在xml中配置interceptor

<mvc:interceptors>
        <mvc:interceptor>
            <mvc:mapping path="/**"/>
            <bean class="net.zicp.xiaochangwei.web.interceptors.SelfPermissionInterceptor"/>
        </mvc:interceptor>
</mvc:interceptors>

第三步:實現對應的interceptor bean

package net.zicp.xiaochangwei.web.interceptors;

import java.lang.annotation.Annotation;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import net.zicp.xiaochangwei.web.annotation.SelfPermission;
import net.zicp.xiaochangwei.web.common.Result;
import net.zicp.xiaochangwei.web.entity.Permission;
import net.zicp.xiaochangwei.web.entity.Role;

import org.apache.commons.collections4.IterableUtils;
import org.apache.commons.collections4.Predicate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;

/**
 * 對有@SelfPermission標簽的方法進行攔截,模擬進行權限檢查
 * 
 * @author xiaochangwei
 *
 */
public class SelfPermissionInterceptor implements HandlerInterceptor {

    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    @Override
    public boolean preHandle(HttpServletRequest request,
            HttpServletResponse response, Object handler) throws Exception {

        request.setCharacterEncoding("UTF-8");
        response.setCharacterEncoding("UTF-8");

        if (handler instanceof HandlerMethod) {
            HandlerMethod handlerMethod = (HandlerMethod) handler;
            SelfPermission permission = getAnnotation(handlerMethod, SelfPermission.class);
            if (permission != null) {
                try {
                    return checkPermission(permission.value());
                } catch (Exception e) {
                    Result result = new Result("120001", "沒得權限", Result.Status.ERROR);
                    response.setContentType("text/plain;charset=UTF-8");
                    response.getWriter().write(JSONObject.toJSONString(result));
                    return false;
                }
            }
        }
        return true;
    }

    @Override
    public void afterCompletion(HttpServletRequest arg0,
            HttpServletResponse arg1, Object arg2, Exception arg3)
            throws Exception {

    }

    @Override
    public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1,
            Object arg2, ModelAndView arg3) throws Exception {
    }

    public boolean checkPermission(final String permissionCode)
            throws Exception {
        String cachedRole = redisTemplate.opsForValue().get("role1");
        if (cachedRole != null) {
            System.out.println("緩存中找到權限數據");
            Role jrole = JSON.parseObject(cachedRole, Role.class);
            boolean result = IterableUtils.matchesAny(jrole.getPermissions(),
                    new Predicate<Permission>() {
                        public boolean evaluate(Permission p) {
                            return permissionCode.equals(p.getPermission());
                        }
                    });

            if (!result) {
                throw new Exception("沒得權限");
            }
            return result;
        } else {
            System.out.println("緩存中沒有找到權限數據");
            return false;
        }
    }

    private <T extends Annotation> T getAnnotation(HandlerMethod handlerMethod,
            Class<T> clazz) {
        T annotation = handlerMethod.getMethodAnnotation(clazz);
        if (annotation != null) {
            return annotation;
        }
        annotation = AnnotationUtils.findAnnotation(handlerMethod.getBeanType(), clazz);
        return annotation;
    }

}

HandlerInterceptor用於攔截,如果有多個的時候,只有上一個返回true才會繼續下一個的執行

 原理很簡單,就是根據xml中配置,當其掃描路徑下的方法被執行時,檢查其上有個沒有定義的注解,如果沒有放行,如果有就根據邏輯判斷確定返回true或者false

true表示驗證成功

false表示驗證失敗

 

同理,我們還可以自定義jsp標簽在頁面上使用,如有權限才顯示相應的東西,前后端必須一同控制才行,如果只前端判斷后端不處理會被繞過,而只后台判斷前端不處理又不友好

直接貼代碼了

1.自定義標簽的實現類,很簡單,繼承TagSupport

package net.zicp.xiaochangwei.web.tag;

import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.TagSupport;

import net.zicp.xiaochangwei.web.entity.Permission;
import net.zicp.xiaochangwei.web.entity.Role;
import net.zicp.xiaochangwei.web.utils.Constant;
import net.zicp.xiaochangwei.web.utils.SpringBeanUtil;

import org.apache.commons.collections4.IterableUtils;
import org.apache.commons.collections4.Predicate;
import org.springframework.data.redis.core.RedisTemplate;

import com.alibaba.fastjson.JSON;

/**
 * @author 肖昌偉 E-mail:317409898@qq.com
 * @version 創建時間:2016年9月18日 上午11:45:06
 * 
 */
public class HasPermissionTag extends TagSupport {
    private static final long serialVersionUID = 1L;
    
    private RedisTemplate<String, String> redisTemplate;
    
    String name = null;
    
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int doStartTag() throws JspException {
        try {
            return isPermitted();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return TagSupport.SKIP_BODY;
    }
    
    public int isPermitted() throws Exception{
        String p = getName();
        boolean show = checkPermission(p);
        if (show) {
            return TagSupport.EVAL_BODY_INCLUDE;
        } else {
            return TagSupport.SKIP_BODY;
        }
    }
    
    @SuppressWarnings("unchecked")
    public boolean checkPermission(final String permissionCode)
            throws Exception {
        redisTemplate = (RedisTemplate<String, String>) SpringBeanUtil.getBean("redisCache");
        String cachedRole = redisTemplate.opsForValue().get(Constant.ROLE+"1");
        if (cachedRole != null) {
            System.out.println("緩存中找到權限數據");
            Role jrole = JSON.parseObject(cachedRole, Role.class);
            boolean result = IterableUtils.matchesAny(jrole.getPermissions(),
                    new Predicate<Permission>() {
                        public boolean evaluate(Permission p) {
                            return permissionCode.equals(p.getPermission());
                        }
                    });

            if (!result) {
                throw new Exception("沒得權限");
            }
            return result;
        } else {
            System.out.println("緩存中沒有找到權限數據");
            return false;
        }
    }
}

2.定義tld文件,直接放在WEB-INF下即可,其它路徑請在web.xml中配置好

<?xml version="1.0" encoding="UTF-8" ?>

<taglib xmlns="http://java.sun.com/xml/ns/j2ee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd"
    version="2.0">
    <description>權限自定義標簽庫</description>
    <tlib-version>1.0</tlib-version>
    <short-name>PermissionTagLibrary</short-name>
    <uri>http://xiaochangwei.com/tags</uri>
     <tag>
        <description>這個標簽的作用是用來判斷有沒有權限</description>
        <name>hasPermission</name>
        <!-- 標簽對應的處理器類-->
        <tag-class>net.zicp.xiaochangwei.web.tag.HasPermissionTag</tag-class>
        <body-content>JSP</body-content>
        <attribute>
          <name>name</name>
          <required>true</required>
          <rtexprvalue>true</rtexprvalue>
        </attribute>
    </tag>
    
</taglib>

3.頁面使用

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%@ taglib uri="http://xiaochangwei.com/tags" prefix="permission" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<link rel="shortcut icon" href="/favicon.ico" />
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>網站首頁</title>
</head>
<body>

<permission:hasPermission name="viewInfo">有權限<br/><br/></permission:hasPermission>

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM