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


    在进行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>
  • 相关阅读:
    时钟同步显示屏(NTP时间显示屏)子母钟系统介绍
    NTP服务器(时钟服务器)为金融交通行业保驾护航
    Moco server Linux 端部署
    Linux 系统下搭建 Gitlab 服务器
    CentOS7 防火墙设置命令
    Allure 环境安装
    Pytest allure 生成测试报告
    Pytest allure 定制化测试报告
    Pytest allure excel 接口自动化框架
    科创人·36氪副总裁王坤:企服产品应重视使用者体验,36氪将推出中国版「魔力象限」
  • 原文地址:https://www.cnblogs.com/xiaochangwei/p/5872132.html
Copyright © 2020-2023  润新知