博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
将shiro作为插件整合到jfinal,在jfinal里读取shiro的注解
阅读量:6612 次
发布时间:2019-06-24

本文共 7869 字,大约阅读时间需要 26 分钟。

hot3.png

学习了shiro的一些身份验证和授权知识,那么现在主要学习大飞怎么把shiro结合到jfinal,怎么在jfinal里使用shiro的注解的。

一、首先,要先了解一下jfinal启动插件的流程,才能好的理解jfinal怎么使用shiro,jfinal使用其他框架都采用Plugins的形式,在启动jfinal的时候,会依次启动在configPlugin里配置的插件,这个插件要实现接口IPlugin就可以,如public class ShiroPlugin implements IPlugin。 jfinal启动继承了IPlugin的插件的流程如下:

1、启动jfinal,会将web.xml的内容都初始化并加载到web容器,即会通过反射给每个类创建一个实例,如下所示:

org.apache.shiro.web.env.EnvironmentLoaderListener
ShiroFilter
org.apache.shiro.web.servlet.ShiroFilter
ShiroFilter
/*
jfinal
com.jfinal.core.JFinalFilter
configClass
com.learnging.system.LearngingConfig
jfinal
/*

这里它会生成JFinalFilter的实例,并调用JFinalFilter的init方法,这里init又委托给JFinal的init方法,如下:

void init(JFinalConfig jfinalConfig, ServletContext servletContext){    this.servletContext = servletContext;    this.contextPath = servletContext.getContextPath();    initPathKit();    Config.configJFinal(jfinalConfig);	// start plugin, init log factory and init engine in this method    constants = Config.getConstants();    initActionMapping();    initHandler();    initRender();    initOreillyCos();    initTokenManager();}

JFinal的init方法又调用Config.configJFinal()方法,如下:

static void configJFinal(JFinalConfig jfinalConfig){    jfinalConfig.configConstant(constants);    initLogFactory();    initEngine();    jfinalConfig.configRoute(routes);    jfinalConfig.configEngine(engine);    jfinalConfig.configPlugin(plugins);    startPlugins();		// very important!!!    jfinalConfig.configInterceptor(interceptors);    jfinalConfig.configHandler(handlers);}
private static void startPlugins(){    List
pluginList = plugins.getPluginList(); if (pluginList == null) { return ; } for (IPlugin plugin : pluginList) { try { // process ActiveRecordPlugin devMode if (plugin instanceof com.jfinal.plugin.activerecord.ActiveRecordPlugin) { com.jfinal.plugin.activerecord.ActiveRecordPlugin arp = (com.jfinal.plugin.activerecord.ActiveRecordPlugin)plugin; if (arp.getDevMode() == null) { arp.setDevMode(constants.getDevMode()); } } if (plugin.start() == false) { String message = "Plugin start error: " + plugin.getClass().getName(); log.error(message); throw new RuntimeException(message); } } catch (Exception e) { String message = "Plugin start error: " + plugin.getClass().getName() + ". \n" + e.getMessage(); log.error(message, e); throw new RuntimeException(message, e); } }}

至此,启动完所有插件,只要一个插件启动失败,就会都失败。

二接下来就是将一个框架做成一个插件,整合到jfinal。大飞写的ShiroPlugin插件最主要的start方法,如下所示:

public boolean start(){    Set
excludedMethodName = buildExcludedMethodName(); ConcurrentMap
authzMaps = new ConcurrentHashMap
(); //逐个访问所有注册的Controller,解析Controller及action上的所有Shiro注解。 //并依据这些注解,actionKey提前构建好权限检查处理器。 for (Route route : routes.getRouteItemList()) { Class
controllerClass = route.getControllerClass(); String controllerKey = route.getControllerKey(); // 获取Controller的所有Shiro注解。 List
controllerAnnotations = getAuthzAnnotations(controllerClass); // 逐个遍历方法。 Method[] methods = controllerClass.getMethods(); for (Method method : methods) { //排除掉Controller基类的所有方法,并且只关注没有参数的Action方法。 if (!excludedMethodName.contains(method.getName()) && method.getParameterTypes().length == 0) { //若该方法上存在ClearShiro注解,则对该action不进行访问控制检查。 if(isClearShiroAnnotationPresent(method)) { continue; } //获取方法的所有Shiro注解。 List
methodAnnotations = getAuthzAnnotations(method); //依据Controller的注解和方法的注解来生成访问控制处理器。 AuthzHandler authzHandler = createAuthzHandler( controllerAnnotations, methodAnnotations); //生成访问控制处理器成功。 if (authzHandler != null) { //构建ActionKey,参考ActionMapping中实现 String actionKey = createActionKey(controllerClass, method, controllerKey); //添加映射 authzMaps.put(actionKey, authzHandler); } } } } //注入到ShiroKit类中。ShiroKit类以单例模式运行。 ShiroKit.init(authzMaps); /** * 设定登录,登录成功,未授权等url地址 */ ShiroKit.setLoginUrl(loginUrl); ShiroKit.setSuccessUrl(successUrl); ShiroKit.setUnauthorizedUrl(unauthorizedUrl); ShiroKit.setExtName(extName); return true;}

1、buildExcludedMethodName()取得controller里没有参数的方法,即action方法。

2、authzMaps用于保存cotroller和action及其上面对应的注解。

3、逐个访问所有注册的Controller,解析Controller及action上的所有Shiro注解。并依据这些注解,actionKey提前构建好权限检查处理器。

4、用controllerAnnotations保存Controller的所有Shiro注解。

5、用methodAnnotations保存不是基类,又没有参数的,又没有ClearShiro的方法的所有Shiro注解。

6、调用方法createAuthzHandler依据Controller的注解和方法的注解来生成访问控制处理器。以上authzHandlers.add(null);是因为注解的处理是有顺序的,依次为RequiresRoles,RequiresPermissions, RequiresAuthentication,RequiresUser,RequiresGuest。

/** * 依据Controller的注解和方法的注解来生成访问控制处理器。 * @param controllerAnnotations  Controller的注解 * @param methodAnnotations 方法的注解 * @return 访问控制处理器 */private AuthzHandler createAuthzHandler(    List
controllerAnnotations, List
methodAnnotations){ //没有注解 if (controllerAnnotations.size() == 0 && methodAnnotations.size() == 0) { return null; } //至少有一个注解 List
authzHandlers = new ArrayList
(AUTHZ_ANNOTATION_CLASSES.length); for (int index = 0; index < AUTHZ_ANNOTATION_CLASSES.length; index++) { authzHandlers.add(null); } // 逐个扫描注解,若是相应的注解则在相应的位置赋值。 scanAnnotation(authzHandlers, controllerAnnotations); // 逐个扫描注解,若是相应的注解则在相应的位置赋值。函数的注解优先级高于Controller scanAnnotation(authzHandlers, methodAnnotations); // 去除空值 List
finalAuthzHandlers = new ArrayList
(); for (AuthzHandler a : authzHandlers) { if (a != null) { finalAuthzHandlers.add(a); } } authzHandlers = null; // 存在多个,则构建组合AuthzHandler if (finalAuthzHandlers.size() > 1) { return new CompositeAuthzHandler(finalAuthzHandlers); } // 一个的话直接返回 return finalAuthzHandlers.get(0);}

7、生成访问控制处理器成功,构建ActionKey,参考ActionMapping中实现,添加映射,大飞实现如下:

/** * 构建actionkey,参考ActionMapping中的实现。 * * @param controllerClass * @param method * @param controllerKey * @return */private String createActionKey(Class 
controllerClass, Method method, String controllerKey){ String methodName = method.getName(); String actionKey = ""; ActionKey ak = method.getAnnotation(ActionKey.class); if (ak != null) { actionKey = ak.value().trim(); if ("".equals(actionKey)) throw new IllegalArgumentException(controllerClass.getName() + "." + methodName + "(): The argument of ActionKey can not be blank."); if (!actionKey.startsWith(SLASH)) actionKey = SLASH + actionKey; } else if (methodName.equals("index")) { actionKey = controllerKey; } else { actionKey = controllerKey.equals(SLASH) ? SLASH + methodName : controllerKey + SLASH + methodName; } return actionKey;}

本博客代码主要来源于jfinal源码和大飞的开源代码。主要目的是学习.

JFinalShiroPlugin下载地址:

转载于:https://my.oschina.net/u/2427561/blog/1524101

你可能感兴趣的文章
【244】◀▶IEW-Unit09
查看>>
Unity5.1 新的网络引擎UNET(十五) Networking 引用--中
查看>>
用任务计划管理计划任务对付任务计划-禁止WPS提示升级
查看>>
Android——SlidingMenu学习总结
查看>>
React-Native 之 GD (十六)首页筛选功能
查看>>
UI概念体系要素
查看>>
SSISDB5:使用TSQL脚本执行Package
查看>>
performSelectorInBackground V.S detachNewThreadSelector?
查看>>
linux,Centos,bash: service: command not found
查看>>
【转】UIColor对颜色的自定义
查看>>
php编译报错 configure: error: Please reinstall the libcurl distribution - easy.h should be in <curl-...
查看>>
asp.net后台进程做定时任务
查看>>
Ural_1671. Anansi's Cobweb(并查集)
查看>>
Web墨卡托坐标与WGS84坐标互转
查看>>
给vs2012换肤
查看>>
java接口中多继承的问题
查看>>
索引笔记《二》确定需要建立索引的列
查看>>
libjpeg的问题
查看>>
MySQL数据库学习笔记(八)----JDBC入门及简单增删改数据库的操作
查看>>
Java Web之Filter
查看>>