APIJSON (twelve: AbstractVerifier source code reading (3))

APIJSON (twelve: AbstractVerifier source code reading (3))

2021SC@SDUSC

verifyAccess

This method is to verify whether the permission is passed

public boolean verifyAccess(SQLConfig config) throws Exception

The parameter passed in is an object in SQLConfig, and what is stored in SQLConfig is the configuration of the database.

First, it will judge whether it is empty, and if it is empty, it will pass directly (although it is not very clear here? Maybe the configuration is not initialized at the beginning, for the convenience of testing?)

String table = config == null ? null : config.getTable();
if (table == null) {
   return true;
}

Then get the role. If the obtained value is empty, the role will be automatically set to UNKNOWN

String role = config.getRole();
if (role == null) {
   role = UNKNOWN;
} 
else { 
   if (ROLE_MAP.containsKey(role) == false) {
      Set<String> NAMES = ROLE_MAP.keySet();
      throw new IllegalArgumentException("角色 " + role + " 不存在!只能是[" + StringUtil.getString(NAMES.toArray()) + "]中的一种!");
   }

   if (role.equals(UNKNOWN) == false) { //未登录的角色
      verifyLogin();
   }
}

After that, the containsKey method in the map is used to determine whether the role exists in the ROLE_MAP. If it does not exist, the keySet method will be used to read the key value in the ROLE_MAP and an error will be reported.

Afterwards, if the role is not UNKNOWN, it will enter the verifyLogin() method to perform login verification.

public void verifyLogin() throws Exception {
   //未登录没有权限操作
   if (visitorId == null) {
      throw new NotLoggedInException("未登录,请登录后再操作!");
   }

   if (visitorId instanceof Number) {
      if (((Number) visitorId).longValue() <= 0) {
         throw new NotLoggedInException("未登录,请登录后再操作!");
      }
   } 
   else if (visitorId instanceof String) {
      if (StringUtil.isEmpty(visitorId, true)) {
         throw new NotLoggedInException("未登录,请登录后再操作!");
      }
   }
   else {
      throw new UnsupportedDataTypeException("visitorId 只能是 Long 或 String 类型!");
   }

}

It will judge whether the visitorId is empty, and whether the type is long or string. If the conditions are not met, a corresponding error will be thrown.

Then get the requested method, and verifyRole to verifyRole () method

RequestMethod method = config.getMethod();
verifyRole(table, method, role);//验证允许的角色

The parameters passed in are table, method, role

public void verifyRole(String table, RequestMethod method, String role) throws Exception {
   Log.d(TAG, "verifyRole  table = " + table + "; method = " + method + "; role = " + role);
   if (table != null) {
      if (method == null) {
         method = GET;
      }
      if (role == null) {
         role = UNKNOWN;
      }
      
      Map<RequestMethod, String[]> map = ACCESS_MAP.get(table);

      if (map == null || Arrays.asList(map.get(method)).contains(role) == false) {
         throw new IllegalAccessException(table + " 不允许 " + role + " 用户的 " + method.name() + " 请求!");
      }
   }
}

First, you can see that the method defaults to GET, and the role defaults to UNKNOWN.

The request is allowed only when the method is included in the map and the corresponding role is included in the method.

The Arrays.asList() method is a method to convert an array into a List collection.

After that, the IdKey of tVisitor will be obtained

String visitorIdkey = getVisitorIdKey(config);

The next step is to judge the role through a switch statement

		switch (role) {
		case LOGIN://verifyRole通过就行
			break;
		case CONTACT:
		case CIRCLE:
			//TODO 做一个缓存contactMap<visitorId, contactArray>,提高[]:{}查询性能, removeAccessInfo时map.remove(visitorId)
			//不能在Visitor内null -> [] ! 否则会导致某些查询加上不需要的条件!
			List<Object> list = visitor.getContactIdList() == null
			? new ArrayList<Object>() : new ArrayList<Object>(visitor.getContactIdList());
			if (role == CIRCLE) {
				list.add(visitorId);
			}

			//key!{}:[] 或 其它没有明确id的条件 等 可以和key{}:list组合。类型错误就报错
			requestId = (Number) config.getWhere(visitorIdkey, true);//JSON里数值不能保证是Long,可能是Integer
			@SuppressWarnings("unchecked") 
			Collection<Object> requestIdArray = (Collection<Object>) config.getWhere(visitorIdkey + "{}", true);//不能是 &{}, |{} 不要传,直接{}
			if (requestId != null) {
				if (requestIdArray == null) {
					requestIdArray = new JSONArray();
				}
				requestIdArray.add(requestId);
			}

			if (requestIdArray == null) {//可能是@得到 || requestIdArray.isEmpty()) {//请求未声明key:id或key{}:[...]条件,自动补全
				config.putWhere(visitorIdkey+"{}", JSON.parseArray(list), true); //key{}:[]有效,SQLConfig里throw NotExistException
			} 
			else {//请求已声明key:id或key{}:[]条件,直接验证
				for (Object id : requestIdArray) {
					if (id == null) {
						continue;
					}
					if (id instanceof Number == false) {//不能准确地判断Long,可能是Integer
						throw new UnsupportedDataTypeException(table + ".id类型错误,id类型必须是Long!");
					}
					if (list.contains(Long.valueOf("" + id)) == false) {//Integer等转为Long才能正确判断。强转崩溃
						throw new IllegalAccessException(visitorIdkey + " = " + id + " 的 " + table
								+ " 不允许 " + role + " 用户的 " + method.name() + " 请求!");
					}
				}
			}
			break;
		case OWNER:
			if (config.getMethod() == RequestMethod.POST) {
				List<String> c = config.getColumn();
				List<List<Object>> ovs = config.getValues();
				if ( (c == null || c.isEmpty()) || (ovs == null || ovs.isEmpty()) ) {
					throw new IllegalArgumentException("POST 请求必须在Table内设置要保存的 key:value !");
				}

				int index = c.indexOf(visitorIdkey);
				if (index >= 0) {
					Object oid;
					for (List<Object> ovl : ovs) {
						oid = ovl == null || index >= ovl.size() ? null : ovl.get(index);
						if (oid == null || StringUtil.getString(oid).equals("" + visitorId) == false) {
							throw new IllegalAccessException(visitorIdkey + " = " + oid + " 的 " + table
									+ " 不允许 " + role + " 用户的 " + method.name() + " 请求!");
						}
					}
				}
				else {
					List<String> nc = new ArrayList<>(c);
					nc.add(visitorIdkey);
					config.setColumn(nc);

					List<List<Object>> nvs = new ArrayList<>();
					List<Object> nvl;
					for (List<Object> ovl : ovs) {
						nvl = ovl == null || ovl.isEmpty() ? new ArrayList<>() : new ArrayList<>(ovl);
						nvl.add(visitorId);
						nvs.add(nvl);
					}

					config.setValues(nvs);
				}
			}
			else {
				requestId = config.getWhere(visitorIdkey, true);//JSON里数值不能保证是Long,可能是Integer
				if (requestId != null && StringUtil.getString(requestId).equals(StringUtil.getString(visitorId)) == false) {
					throw new IllegalAccessException(visitorIdkey + " = " + requestId + " 的 " + table
							+ " 不允许 " + role + " 用户的 " + method.name() + " 请求!");
				}

				config.putWhere(visitorIdkey, visitorId, true);
			}
			break;
		case ADMIN://这里不好做,在特定接口内部判。 可以是  /get/admin + 固定秘钥  Parser#needVerify,之后全局跳过验证
			verifyAdmin();
			break;
		default://unknown,verifyRole通过就行
			break;
		}

Take OWNER as an example. First, it will judge whether the Method is RequestMethod.POST, and then it will judge whether the column and value are empty. If it is empty, an error will be thrown.

After that, the indexOf method will be used to search for the visitorIdkey. If found, the visitorIdkey will be compared with the visitorId. If they do not match, a prompt that the request is not allowed will be thrown.

If not found, visitorIdkey and visitorId will be added to the corresponding List. Finally added into SQLconfig.

If it is another method, the visitorIdkey will be obtained through getWhere, and it will be compared with the visitorId. If it is inconsistent, a prompt that the request is not allowed will be thrown.

Guess you like

Origin blog.csdn.net/qq_50861917/article/details/122018021