<-- home

SecurityContext'e ulaşmak

Spring Security’yle entegre çalışan bir uygulamada, kullanıcıların oturumlarına yönelik bilgiler SecurityContext nesnelerinde tutuluyor. SecurityContext nesneleri ise SecurityContextHolder içerisinde tutuluyor. Varsayılan olarak SecurityContextHolder, SecurityContext nesnelerini ThreadLocal kullanarak saklıyor. Böylelikle aynı thread’de çalışan metodlar aynı SecurityContext nesnesine ulaşabiliyorlar. SecurityContextHolder’in çalışma modu da istenildiği takdirde değiştirilebiliyor.

Uygulamanın oturumla alakalı işlerini Spring Security halletse de, bazen oturum açan kullanıcıya yönelik bilgiler bize de gerekebiliyor. Bunun için öncelikle SecurityContext nesnesine ulaşmamız gerekiyor. Onu da şöyle yapabiliyoruz.

SecurityContext securityContext = SecurityContextHolder.getContext();

Bu çağrıyla elde ettiğimiz securityContext üzerinden Authentication ve UserPrincipal’a erişebiliyoruz. Fakat bu kullanım şurdaki abimin dediği gibi test edilebilirliği bozuyor. Bunun için bu çağrıyı gizlemek daha uygun bir yaklaşım.

 

public class SecurityContextUtils {
        public SecurityContext getSecurityContext() {
		return SecurityContext.getContext();
	}
}

SecurityContextUtils sınıfının içine UserPrincipal veya username’i de getiren metodlar yazılabilir. Bu yöntemle statik metod çağrısını, normal bir metodun içerisine gizledik ve SecurityContextUtils’i ve SecurityContext’i mocklayabilir hale geldik.

Uygulamada Spring de kullanıyorsak şöyle bir sınıf da yazabiliriz.

@Component
public class SecurityContextUtils {
	private SecurityContextHolderStrategy securityContextHolderStrategy;

	@PostConstruct
	void init() {
		securityContextHolderStrategy = SecurityContextHolder
				.getContextHolderStrategy();
	}

	public SecurityContext getSecurityContext() {
		return securityContextHolderStrategy.getContext();
	}
}

SecurityContext nesneleri HTTP request’leri boyunca ThreadLocal’de tutuluyor. Request sonlanınca, ilgili SecurityContext ThreadLocal’den silinip bir sonra request’te tekrar ThreadLocal’e alınıyor. Bunun sebebi ise request’in sonlandığı thread’in, servlet container’in thread pool’una alınıp başka bir request’i ele alması ihtimali. Eski SecurityContext ThreadLocal’den silinmezse thread’de çalışan yeni request yanlış SecurityContext nesnesine erişir. Bu durumu düşünmemiş olmamdan dolayı, ben bir hatayla karşılaştım; onu da yazmak istiyorum. Spring Security filtrelerini kapattığım bir URL’e sahip sayfada, SecurityContext’e erişmeye çalıştım. Filtreler kapalı olduğundan SecurityContext nesnesine ThreadLocal’e alınmıyordu ve erişmeye çalıştığımda null dönüyordu. Buna dikkat etmek gerekiyor.