zoukankan      html  css  js  c++  java
  • Struts2中基于Annotation的细粒度权限控制

    Struts2中基于Annotation的细粒度权限控制  

    2009-10-19 14:25:53|  分类: Struts2 |  标签: |字号 订阅

     
     

          权限控制是保护系统安全运行很重要的一扇门。在web应用里,仅仅隐藏url是不够的。由于web应用是以请求/响应为单位的,我 们的权限控制的粒度只有达到这个程度才能让全国人民放心。在java web开发的世界里,MVC框架的使用再平常不过,大都是将请求拦截后,控制器根据配置文件将请求转给某个函数来处理。下面看看在struts2中我们可 以用的几种方案:

          1、在每个函数里进行权限校验

          这主意实在是简单,缺点我就不说了~太多了~

          2、在每个请求对应的Action的配置项里配置参数,用以标示访问此Action需要的权限,再用拦截器处理

          以 前我这么做过,比方案1好很多,不过这注定你无法实现ZeroConfig。在ROR的促进下,约定优于配置渐渐深入人心。本人就极其反感大量的配置文 件。但是由于权限配置提到XML里配置,最大的好处就是我不必重新编译代码就能改变权限关联。不过情况下遇到需求变更,你会有一种宁可去改代码的冲动。

          3、结合Java的Annotation和Struts2的拦截器控制权限

          下面是上午没事写的一个示例:访问login.jsp,登录,功能有eat和drink,用户登陆后只能访问已授权的功能链接。

          基本思想:对每个Action方法进行注解,并注入一个资源字符串,部署一个拦截器,在每个请求之前拦截一下,通过反射拿到所调用的方法及其注解,依此来进行权限校验。

          优点:

          简单、可行性高

          不修改MVC框架配置文件

          不影响Action内的业务逻辑

          注解的原则之一就是不影响代码的运行,这也实现了本方案的可插拔性、独立性高

          更高的可配置性

          缺点:

          不知道对性能影响如何

          代码基本上都贴到下面了,不想细讲了,有兴趣的可以留言讨论,觉得我火星的就不要拍砖了,有需要eclipse工程源码的发邮件问我要shoru#163.com。

    Struts2中基于Annotation的细粒度权限控制 - uzoice - 专心致志

          (1)Annotation相关

    Access

     1package com.shoru.access;

     2

     3import java.lang.annotation.ElementType;

     4import java.lang.annotation.Retention;

     5import java.lang.annotation.RetentionPolicy;

     6import java.lang.annotation.Target;

     7

     8/** *//**

     9 * 访问控制注解

    10 * 该注解保留到运行时,针对方法使用,默认为BLOCK

    11 * @author Shoru

    12 * @version 0.1

    13 */

    14@Retention(RetentionPolicy.RUNTIME)

    15@Target(ElementType.METHOD)

    16public @interface Access {

    17    String[] value() default { AccessOption.BLOCK };

    18}

     

    AccessOption

     1package com.shoru.access;

     2

     3/** *//**

     4 * 访问控制接口,定义默认的控制常量

     5 * @author Shoru

     6 * @version 0.1

     7 */

     8public interface AccessOption {

     9    /** *//**

    10     * 拦截访问

    11     */

    12    public static String BLOCK="block";

    13    /** *//**

    14     * 通过访问

    15     */

    16    public static String PASS="pass";

    17    /** *//**

    18     * 要求登录

    19     */

    20    public static String LOGIN="login";

    21}

     

    UserAccessOption

     1package com.shoru.access;

     2

     3

     4/** *//**

     5 * 用户自定义控制接口,继承自AccessOption

     6 * 可将系统权限全部定义到此处,格式为:权限名=资源名

     7 * @author Shoru

     8 * @see AccessOption

     9 */

    10public interface UserAccessOption extends AccessOption {

    11    public static String EAT = "eat";

    12    public static String DRINK = "drink";

    13}

     

          (2)Action类

    AccessAction

     1package com.shoru.access.action;

     2

     3import java.util.ArrayList;

     4import java.util.List;

     5

     6import com.opensymphony.xwork2.Action;

     7import com.opensymphony.xwork2.ActionContext;

     8import com.shoru.access.Access;

     9import com.shoru.access.UserAccessOption;

    10

    11public class AccessAction implements Action {

    12    @Access

    13    public String execute() throws Exception {

    14        return SUCCESS;

    15    }

    16

    17    @Access(UserAccessOption.PASS)

    18    public String index() throws Exception {

    19        /**//*

    20         * 此处模拟权限的获取

    21         */

    22        List<String> accessPoints = new ArrayList<String>();

    23        /**//*

    24         * 赋予eat权限

    25         */

    26        accessPoints.add("eat");

    27        ActionContext.getContext().getSession().put("access", accessPoints);

    28        return SUCCESS;

    29    }

    30

    31    @Access(UserAccessOption.DRINK)

    32    public String drink() throws Exception {

    33        return SUCCESS;

    34    }

    35

    36    @Access( { UserAccessOption.EAT })

    37    public String eat() throws Exception {

    38        return SUCCESS;

    39    }

    40}

     

          (3)拦截器

    AccessInterceptor

     1package com.shoru.access.interceptor;

     2

     3import java.lang.annotation.Annotation;

     4import java.lang.reflect.Method;

     5import java.util.List;

     6

     7import com.opensymphony.xwork2.ActionContext;

     8import com.opensymphony.xwork2.ActionInvocation;

     9import com.opensymphony.xwork2.interceptor.Interceptor;

    10import com.opensymphony.xwork2.util.AnnotationUtils;

    11import com.shoru.access.Access;

    12import com.shoru.access.AccessOption;

    13

    14public class AccessInterceptor implements Interceptor {

    15

    16    private static final long serialVersionUID = -1066389312400000758L;

    17

    18    List<String> accessPoints = null;

    19

    20    public void init() {

    21

    22    }

    23

    24    public void destroy() {

    25        accessPoints = null;

    26    }

    27

    28    public String intercept(ActionInvocation invocation) throws Exception {

    29        if (accessPoints == null) {

    30            /**//*

    31             * 获取权限列表

    32             */

    33            accessPoints = (List<String>) ActionContext.getContext()

    34                    .getSession().get("access");

    35        }

    36        /**//*

    37         * 获取此次调用的方法名

    38         */

    39        String method = invocation.getProxy().getMethod();

    40        /**//*

    41         * 获取所有已注解方法

    42         */

    43        List<Method> methods = AnnotationUtils.findAnnotatedMethods(invocation

    44                .getAction().getClass(), Access.class);

    45        /**//*

    46         * 迭代所有已注解方法

    47         */

    48        for (Method m : methods) {

    49            if (m.getName().equals(method)) {

    50                /**//*

    51                 * 获取被调用方法的注解

    52                 */

    53                Annotation annotation = m.getAnnotation(Access.class);

    54                /**//*

    55                 * 放过不需要校验权限列表的请求,e.g.登录、验证码

    56                 */

    57                for (String s : ((Access) annotation).value()) {

    58                    if (s.equals(AccessOption.PASS)) {

    59                        return invocation.invoke();

    60                    }

    61                }

    62                /**//*

    63                 * 权限列表为空,返回登录

    64                 */

    65                if (accessPoints == null) {

    66                    return AccessOption.LOGIN;

    67                }

    68                /**//*

    69                 * 迭代方法注解里的值,判断是否存在于权限列表中

    70                 */

    71                for (String s : ((Access) annotation).value()) {

    72                    if (accessPoints.indexOf(s) != -1) {

    73                        /**//*

    74                         * 权限校验通过

    75                         */

    76                        return invocation.invoke();

    77                    }

    78                }

    79            }

    80        }

    81        /**//*

    82         * 没有对方法进行注解或者权限校验不通过,拦截此次请求

    83         */

    84        return AccessOption.BLOCK;

    85    }

    86}

          (4)struts.xml

    struts.xml

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

     2<!DOCTYPE struts PUBLIC

     3    "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"

     4    "http://struts.apache.org/dtds/struts-2.0.dtd">

     5<struts>

     6    <package name="access" extends="struts-default">

     7        <interceptors>

     8            <!-- 权限拦截器 -->

     9            <interceptor name="access"

    10                class="com.shoru.access.interceptor.AccessInterceptor"></interceptor>

    11            <interceptor-stack name="my-default">

    12                <interceptor-ref name="access"></interceptor-ref>

    13                <interceptor-ref name="defaultStack"></interceptor-ref>

    14            </interceptor-stack>

    15        </interceptors>

    16        <default-interceptor-ref name="my-default"></default-interceptor-ref>

    17        <global-results>

    18            <result name="block">/login.jsp</result>

    19            <result name="login">/login.jsp</result>

    20        </global-results>

    21        <!-- Zero Config All Actions -->

    22        <action name="*" class="com.shoru.access.action.AccessAction"

    23            method="{1}">

    24            <result>/{1}.jsp</result>

    25        </action>

    26

  • 相关阅读:
    mysql常用命令
    CSS样式
    定位
    background
    文本属性和字体属性
    超链接导航案例
    margin塌陷
    浮动
    GIT 修改提交地址
    VUE ElementUI 表格多选框实现单选
  • 原文地址:https://www.cnblogs.com/langtianya/p/3169476.html
Copyright © 2011-2022 走看看