欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

使用spring拦截器手写权限认证框架

程序员文章站 2022-07-21 17:10:27
1、新建用户对象封装的实体类 2、使用单例模式创建用户对象的容器 3、封装成用户对象操作的工具类 4、拦截器的实现 5、把拦截器注入岛spring容器中,配置跨域,使用spring定时器,定时清除过期用户 6、测试 未做压力测试,适合做后台管理系统使用,并发高的项目慎用。 ......

1、新建用户对象封装的实体类

*
 * 主体类
 * wmy 13:20 2019/8/15
 * @param
 * @return
 **/
public class subject {
    private object bean;
    private string token;
    private date expired;

    public string gettoken() {
        return token;
    }

    public void settoken(string token) {
        this.token = token;
    }

    public date getexpired() {
        return expired;
    }

    public void setexpired(date expired) {
        this.expired = expired;
    }

    public object getbean() {
        return bean;
    }

    public void setbean(object bean) {
        this.bean = bean;
    }

    @override
    public string tostring() {
        return "subject{" +
                "bean=" + bean +
                ", token='" + token + '\'' +
                ", expired=" + expired +
                '}';
    }
}

2、使用单例模式创建用户对象的容器

  @bean("tokens")
    public map<string, subject> gettokens() {
        map<string, subject> tokens = new hashmap<>();
        return tokens;
    }

3、封装成用户对象操作的工具类

@component
public class subjectutil implements beanfactoryaware {

    private static beanfactory beanfactory = null;

    private static string token = null;

    public static string gettoken() {
        return token;
    }

    public static void settoken(string token) {
        subjectutil.token = token;
    }

    @override
    public void setbeanfactory(beanfactory beanfactory) throws beansexception {
        subjectutil.beanfactory = beanfactory;
    }

    public static beanfactory getbeanfactory() {
        return beanfactory;
    }

    /*
     * 获得当前用户id
     * wmy 15:29 2019/8/19
     * @param []
     * @return java.lang.integer
     **/
    public static integer getsubjectid() {
       return subjectutil.getbean(token,branduserr.class).getid();
    }

    /*
     * 厂商id
     * wmy 9:44 2019/8/26
     * @param []
     * @return java.lang.integer
     **/
    public static integer getbrandid() {
        return subjectutil.getbean(token,branduserr.class).getbrandid();
    }
    /*
     * 获得在线用户封装
     **/
    public static subject getsubject(string token) {

        map<string, subject> beans = (map<string, subject>) beanfactory.getbean("tokens");
        return beans.get(token);
    }

    /*
     * 获得在线用户
     **/
    public static object getbean(string token) {
        map<string, subject> beans = (map<string, subject>) beanfactory.getbean("tokens");
        subject subject = beans.get(token);
        if (subject != null) {
            return subject.getbean();
        }
        return null;
    }

    //获得在线用户
    public static final <t> t getbean(string token, class<t> clazz) {

        map<string, subject> beans = (map<string, subject>) beanfactory.getbean("tokens");
        subject subject = beans.get(token);
        if (subject != null) {
            object bean = subject.getbean();
            if (clazz.isinstance(bean)) {
                return clazz.cast(bean);
            }
        }
        return null;
    }

    /*
     * 添加在线用户
     **/
    public static void addtokenbean(string token, object bean, date expired) {

        object beans = beanfactory.getbean("tokens");
        if (beans != null && beans instanceof map) {
            map<string, subject> map = (map<string, subject>) beans;
            if (!map.containskey(token)) {
                subject subject = new subject();
                subject.setbean(bean);
                subject.setexpired(expired);
                subject.settoken(token);
                map.put(token, subject);
            }
        }
    }

    /*
     * 删除用户
     **/
    public static void removetokenbean(string token) {

        map<string, subject> beans = (map<string, subject>) beanfactory.getbean("tokens");
        beans.remove(token);
    }


    /*
     * 获得所有在线用户
     * wmy 10:53 2019/8/19
     * @param []
     * @return java.util.map<java.lang.string,com.raise3d.config.subject>
     **/
    public static map<string, subject> getbeans() {
        object beans = beanfactory.getbean("tokens");
        if (beans != null && beans instanceof map) {
            map<string, subject> map = (map<string, subject>) beans;
            return map;
        }
        return null;
    }

    /*
     * 清楚所有用户
     * wmy 13:02 2019/8/19
     * @param []
     * @return void
     **/
    public static void clear() {
        object beans = beanfactory.getbean("tokens");
        if (beans != null && beans instanceof map) {
            map<string, subject> map = (map<string, subject>) beans;
            map.clear();
        }
    }
}

4、拦截器的实现

/*
 * 登录拦截器
 * wmy 14:02 2019/8/19
 * @param
 * @return
 **/
public class logininterceptor implements handlerinterceptor {
    @override
    public boolean prehandle(httpservletrequest request, httpservletresponse response, object handler) throws exception {
        if (!request.getmethod().equals("options")) {
            string token = request.getheader("authorization");
            int verify = verify(token);
            if (verify == 0) {
                printwriter writer = response.getwriter();
                writer.write(config.msg_access_denied);
                return false;
            } else if (verify == 2) {
                printwriter writer = response.getwriter();
                writer.write(config.msg_access_expired);
                return false;
            } else if (subjectutil.gettoken() == null) {
                printwriter writer = response.getwriter();
                writer.write(config.msg_access_denied);
                return false;
            }
        }
        return true;
    }

    @override
    public void posthandle(httpservletrequest request, httpservletresponse response, object handler, modelandview modelandview) throws exception {

    }

    @override
    public void aftercompletion(httpservletrequest request, httpservletresponse response, object handler, exception ex) throws exception {
        subjectutil.settoken(null);
    }

    /*
     * 认证方法
     * wmy 11:29 2019/8/15
     * @param [token]
     * @return java.lang.boolean
     **/
    public synchronized int verify(string token) {
        if (token != null) try {
            subject subject = subjectutil.getsubject(token);
            if (subject != null) {
                //判断是否过期
                if (subject.getexpired().gettime() + config.msg_expired < system.currenttimemillis()) {
                    return 2;
                } else {
                    if (!token.equals(subjectutil.gettoken())) {
                        while (true) {
                            if (subjectutil.gettoken() == null) {
                                subjectutil.settoken(token);
                                return 1;
                            }
                            system.out.println("********** token切换中 *********");
                        }
                    }
                    return 1;
                }
            }
        } catch (exception e) {
            e.printstacktrace();
        }
        return 0;
    }
}

5、把拦截器注入岛spring容器中,配置跨域,使用spring定时器,定时清除过期用户

@configuration
@enablescheduling
public class webmvcconfig extends webmvcconfigureradapter {


    @override
    public void addinterceptors(interceptorregistry registry) {
        registry.addinterceptor(new logininterceptor()).addpathpatterns("/**").excludepathpatterns("/branduser/login");
    }

    @override
    public void addcorsmappings(corsregistry registry) {
        registry.addmapping("/**").allowedorigins("*");
    }


    @bean("tokens")
    public map<string, subject> gettokens() {
        map<string, subject> tokens = new hashmap<>();
        return tokens;
    }


    @scheduled(fixeddelay = 2 * 60 * 60 * 1000)//两个小时执行一次
    private void expiredtokens() {
        map<string, subject> beans = subjectutil.getbeans();
        set<string> tokens = new hashset<>();
        if (beans.size() > 0) {
            for (string key : beans.keyset()) {
                if (beans.get(key).getexpired().gettime() + config.msg_expired < system.currenttimemillis()) {
                    tokens.add(key);
                }
            }
            if (tokens.size() > 0) {
                tokens.stream().foreach(token -> subjectutil.removetokenbean(token));
            }
        }
    }

}

6、测试

   @postmapping("/test")
    public result test() {

        string token = subjectutil.gettoken();
        branduserr bean = subjectutil.getbean(token, branduserr.class);
        return result.ok(bean);

    }

    @postmapping("/test2")
    public result test2() {
        //subjectutil.clear();
        return result.ok(subjectutil.getbean(subjectutil.gettoken()));
    }

使用spring拦截器手写权限认证框架

使用spring拦截器手写权限认证框架

未做压力测试,适合做后台管理系统使用,并发高的项目慎用。