自动化测试特定区域滑动_自动化用户特定实体的访问控制
自動(dòng)化測(cè)試特定區(qū)域滑動(dòng)
實(shí)際上,每個(gè)Web應(yīng)用程序都應(yīng)該有多個(gè)用戶(hù),并且每個(gè)用戶(hù)都有一些數(shù)據(jù)-帖子,文檔,消息等等。 最明顯的事情是保護(hù)這些實(shí)體免遭非這些資源合法所有者的用戶(hù)獲取。
不幸的是,這不是最容易的事情。 我并不是說(shuō)很難,它不像簡(jiǎn)單地返回資源那樣直觀。 當(dāng)您是/record/{recordId}端點(diǎn)時(shí),您將立即執(zhí)行對(duì)recordId的數(shù)據(jù)庫(kù)查詢(xún)。 只有這樣,才需要檢查此記錄是否屬于當(dāng)前經(jīng)過(guò)身份驗(yàn)證的用戶(hù)。
框架在這里沒(méi)有幫助,因?yàn)檫@種訪問(wèn)控制和所有權(quán)邏輯是特定于域的。 沒(méi)有明顯的通用方法來(lái)定義所有權(quán)。 它取決于實(shí)體模型和實(shí)體之間的關(guān)系。 在某些情況下,它可能非常復(fù)雜,其中涉及在聯(lián)接表中查找(用于多對(duì)多關(guān)系)。
但是您應(yīng)該自動(dòng)執(zhí)行此操作,原因有兩個(gè)。 首先,在每個(gè)端點(diǎn)/控制器方法上手動(dòng)執(zhí)行這些檢查很繁瑣,并且使代碼難看。 其次,更容易忘記添加這些檢查,尤其是在有新開(kāi)發(fā)人員的情況下。
您可以在DAO的所有地方進(jìn)行這些檢查,但通常應(yīng)盡早失敗,因此這些檢查應(yīng)在控制器(端點(diǎn)處理程序)級(jí)別上進(jìn)行。 對(duì)于Java和Spring,可以使用批注和HandlerInterceptor來(lái)自動(dòng)執(zhí)行此操作。 在使用任何其他語(yǔ)言或框架的情況下,也可以使用類(lèi)似的方法-一些可插入的方式來(lái)描述要檢查的所有權(quán)關(guān)系。
以下是放置在每個(gè)控制器方法上的示例注釋:
public @interface VerifyEntityOwnership {String entityIdParam() default "id";Class<?> entityType(); }然后定義攔截器(當(dāng)然,應(yīng)將其配置為執(zhí)行)
@Component public class VerifyEntityOwnershipInterceptor extends HandlerInterceptorAdapter {private static final Logger logger = LoggerFactory.getLogger(VerifyEntityOwnershipInterceptor.class);@Autowiredprivate OrganizationService organizationService;@Autowiredprivate MessageService MessageService;@Autowiredprivate UserService userService;@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {Authentication authentication = SecurityContextHolder.getContext().getAuthentication();// assuming spring-security with a custom authentication token typeif (authentication instanceof ApiAuthenticationToken) {AuthenticationData authenticationData = ((ApiAuthenticationToken) authentication).getAuthenticationData();UUID clientId = authenticationData.getClientId();HandlerMethod handlerMethod = (HandlerMethod) handler;VerifyEntityOwnership annotation = handlerMethod.getMethodAnnotation(VerifyEntityOwnership.class);if (annotation == null) {logger.warn("No VerifyEntityOwnership annotation found on method {}", handlerMethod.getMethod().getName());return true;}String entityId = getParam(request, annotation.entityIdParam());if (entityId != null) {if (annotation.entityType() == User.class) {User user = userService.get(entityId);if (!user.getClientId().equals(clientId)) {return false;}} else if (annotation.entityType() == Message.class) {Message record = messageService.get(entityId);if (!message.getClientId().equals(clientId) {return false;}} // .... more}}return true;}@SuppressWarnings("unchecked")private String getParam(HttpServletRequest request, String paramName) {String value = request.getParameter(paramName);if (value != null) {return value;}Map<String, String> pathVariables = (Map<String, String>) request.getAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE);return pathVariables.get(paramName);} }您會(huì)看到這假定每種類(lèi)型都需要自定義邏輯。 如果您的模型很簡(jiǎn)單,則可以使之通用–使所有實(shí)體都使用它們都定義的getClientId()方法實(shí)現(xiàn)某些Owned接口。 然后只需擁有dao.get(id, entityClass); 并避免使用特定于實(shí)體的邏輯。
請(qǐng)注意,當(dāng)方法上沒(méi)有注釋時(shí),將顯示警告-那里表示您可能已忘記添加一個(gè)方法。 某些端點(diǎn)可能不需要所有權(quán)檢查–對(duì)于它們,您可以具有特殊的@IgnoreEntityOwnership批注。 關(guān)鍵是要做出有意識(shí)的決定,不驗(yàn)證所有權(quán),而不是忘記所有權(quán)并引入安全問(wèn)題。
我的意思可能很明顯。 但是我已經(jīng)看到了許多這種遺漏的例子,包括生產(chǎn)政府項(xiàng)目。 就像我說(shuō)的,框架不會(huì)強(qiáng)迫您考慮這一方面,因?yàn)樗鼈儾荒芤酝ㄓ玫姆绞阶龅竭@一點(diǎn)– Web框架通常與實(shí)體模型無(wú)關(guān),而ORM與控制器無(wú)關(guān)。 有處理所有這些方面的綜合框架,但是即使它們沒(méi)有通用的機(jī)制 (至少我沒(méi)有意識(shí)到)。
安全性包括將一套良好實(shí)踐和原則應(yīng)用于系統(tǒng)。 但是,它還包括一些程序和自動(dòng)化程序,這些程序和自動(dòng)化程序可以幫助開(kāi)發(fā)人員和管理員不要忽略他們通常知道的東西,而會(huì)時(shí)不時(shí)地忘記。 而且,應(yīng)用安全性原則越乏味,則一貫地應(yīng)用它的可能性就越大。
翻譯自: https://www.javacodegeeks.com/2018/10/automate-access-control-user-entities.html
自動(dòng)化測(cè)試特定區(qū)域滑動(dòng)
總結(jié)
以上是生活随笔為你收集整理的自动化测试特定区域滑动_自动化用户特定实体的访问控制的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: idea 构建spring_以Sprin
- 下一篇: 不停机与停机更新_Istio的零停机滚动