• 自定义注解实现权限管理框架或其它功能扩充


    在进行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>
  • 相关阅读:
    网络安全分析
    java实现 洛谷 P1464 Function
    java实现 洛谷 P1464 Function
    java实现 洛谷 P1014 Cantor表
    java实现 洛谷 P1014 Cantor表
    java实现 洛谷 P1014 Cantor表
    java实现 洛谷 P1014 Cantor表
    java实现 洛谷 P1014 Cantor表
    java实现 洛谷 P1540 机器
    java实现 洛谷 P1540 机器
  • 原文地址:https://www.cnblogs.com/xiaochangwei/p/5872132.html
Copyright © 2020-2023  润新知