SSH开发 | 配合自定义注解 和 Stratus拦截器,实现 方法级粒度 用户鉴权

Posted bukong

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SSH开发 | 配合自定义注解 和 Stratus拦截器,实现 方法级粒度 用户鉴权相关的知识,希望对你有一定的参考价值。

1.提要

  本文是 小小商城-SSH版的 细节详解系列 之一,项目 github:https://github.com/xenv/S-mall-ssh 本文代码大部分在 github 中 可以找到。

  有用户系统,就必须有配套的鉴权系统来确保页面不被非法访问。市面上的鉴权系统,最为成熟的就是shiro,但是体量太重,使用也不太方便,对代码的侵入型也比较强,所以我简单使用 自定义注解 和 Stratus拦截器 就实现了一个 简单 的鉴权系统,虽然不及 shiiro 稳定和功能强大,但是也足够使用,并且配置非常简单。

2.具体实现

  原理其实非常简单,先在 action 类和 方法上配置好自定义注解,然后配置一个拦截器读取这些注解,在和 session 里面的 user 比对 权限,判断是否放行即可。

  在配置自定义注解时,我选择了类和方法同时配置,方法如果不配置则使用类的权限配置。

  1. 在User实体类中,用enum定义用户组

 public enum Group{
        unLogin,user,admin,superAdmin;
 }

  2. 定义一个自定义注解

@Retention(RetentionPolicy.RUNTIME) // 运行时可以被获取
@Target({METHOD,TYPE}) //加载类上或者方法上面
@Inherited //可以子类继承
public @interface Auth {
    User.Group value(); //User.Group是一个enum类型,在User实体类中定义
}

  3. 在 action 类中加入这个自定义注解

  比如前台的 Action 中,可以在 action 类上面加一个 @Auth(User.Group.unLogin) ,这样该 action 类下面的所有方法 unLogin 用户都可以访问。对于不想要 unLogin 用户 访问 的方法,可以在那个方法上面加上 @Auth(User.Group.user) ,就会覆盖掉  类的权限配置。

  4.配置一个拦截器实现鉴权动作

public class AuthInterceptor extends AbstractInterceptor {
    @Override
    public String intercept(ActionInvocation actionInvocation) throws Exception {
        //获取访问页面的权限
        //获取方法上的注解
        Object action =actionInvocation.getAction();
        String methodName=actionInvocation.getProxy().getMethod();
        Auth authInMethod=action.getClass().getMethod(methodName).getAnnotation(Auth.class);
        //获取类上的注解
        Auth authInClass = action.getClass().getAnnotation(Auth.class);
        //获取Enum方法的ordinal,根据大小来确定该页面权限
        int pageRate = authInClass==null?0:authInClass.value().ordinal();
        pageRate = authInMethod == null?pageRate:authInMethod.value().ordinal();


        //获取用户的权限
        int userRate = 0;
        User user = (User) ActionContext.getContext().getSession().get("user");
        if(user!=null){
            userRate = user.getGroup().ordinal();
        }

        //根据权限决定是否放行
        if(pageRate>userRate){
            if(userRate == 0) {
                ServletActionContext.getResponse().sendRedirect("/login");
                return null;
            }
            return "/noAuth";
        }
        return  actionInvocation.invoke();
    }
}

  5.使拦截器生效,在struts.xml中配置

    <package name="basic-struts" extends="struts-default">
        <interceptors>
            <interceptor name="authInterceptor" class="tmall.interceptor.AuthInterceptor" />

            <interceptor-stack name="myInterceptors">
                <interceptor-ref name="authInterceptor"/>
                <interceptor-ref name="defaultStack"/>
            </interceptor-stack>
        </interceptors>
        <default-interceptor-ref name="myInterceptors" />
        <global-results>
            <result name="/noAuth">/noAuth</result>
        </global-results>
    </package>

  OK,大功告成。

以上是关于SSH开发 | 配合自定义注解 和 Stratus拦截器,实现 方法级粒度 用户鉴权的主要内容,如果未能解决你的问题,请参考以下文章

aop配合自定义的注解使用,静态类获取request

java注解开发是啥?是否不用在xml里配置ssh?以前都是配置xml,注解让我晕了

AspectJ注解

MyBatis注解开发---实现自定义映射关系和关联查询

springboot系列(二十一):基于AOP实现自定义注解且记录接口日志|超级超级详细,建议收藏

自定义校验注解的开发