📄 securitycontextholdertests.java
字号:
/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */package org.acegisecurity.context;import junit.framework.ComparisonFailure;import junit.framework.TestCase;import org.acegisecurity.providers.UsernamePasswordAuthenticationToken;import java.util.Random;/** * Tests {@link SecurityContextHolder}. * * @author Ben Alex * @version $Id: SecurityContextHolderTests.java 1788 2007-03-10 21:34:53Z luke_t $ */public class SecurityContextHolderTests extends TestCase { //~ Static fields/initializers ===================================================================================== private static int errors = 0; private static final int NUM_OPS = 25; private static final int NUM_THREADS = 10; //~ Constructors =================================================================================================== public SecurityContextHolderTests() { super(); } public SecurityContextHolderTests(String arg0) { super(arg0); } //~ Methods ======================================================================================================== private void loadStartAndWaitForThreads(boolean topLevelThread, String prefix, int createThreads, boolean expectAllThreadsToUseIdenticalAuthentication, boolean expectChildrenToShareAuthenticationWithParent) { Thread[] threads = new Thread[createThreads]; errors = 0; if (topLevelThread) { // PARENT (TOP-LEVEL) THREAD CREATION if (expectChildrenToShareAuthenticationWithParent) { // An InheritableThreadLocal for (int i = 0; i < threads.length; i++) { if ((i % 2) == 0) { // Don't inject auth into current thread; neither current thread or child will have authentication threads[i] = makeThread(prefix + "Unauth_Parent_" + i, true, false, false, true, null); } else { // Inject auth into current thread, but not child; current thread will have auth, child will also have auth threads[i] = makeThread(prefix + "Auth_Parent_" + i, true, true, false, true, prefix + "Auth_Parent_" + i); } } } else if (expectAllThreadsToUseIdenticalAuthentication) { // A global SecurityContextHolder.getContext() .setAuthentication(new UsernamePasswordAuthenticationToken("GLOBAL_USERNAME", "pass")); for (int i = 0; i < threads.length; i++) { if ((i % 2) == 0) { // Don't inject auth into current thread;both current thread and child will have same authentication threads[i] = makeThread(prefix + "Unauth_Parent_" + i, true, false, true, true, "GLOBAL_USERNAME"); } else { // Inject auth into current thread; current thread will have auth, child will also have auth threads[i] = makeThread(prefix + "Auth_Parent_" + i, true, true, true, true, "GLOBAL_USERNAME"); } } } else { // A standard ThreadLocal for (int i = 0; i < threads.length; i++) { if ((i % 2) == 0) { // Don't inject auth into current thread; neither current thread or child will have authentication threads[i] = makeThread(prefix + "Unauth_Parent_" + i, true, false, false, false, null); } else { // Inject auth into current thread, but not child; current thread will have auth, child will not have auth threads[i] = makeThread(prefix + "Auth_Parent_" + i, true, true, false, false, prefix + "Auth_Parent_" + i); } } } } else { // CHILD THREAD CREATION if (expectChildrenToShareAuthenticationWithParent || expectAllThreadsToUseIdenticalAuthentication) { // The children being created are all expected to have security (ie an InheritableThreadLocal/global AND auth was injected into parent) for (int i = 0; i < threads.length; i++) { String expectedUsername = prefix; if (expectAllThreadsToUseIdenticalAuthentication) { expectedUsername = "GLOBAL_USERNAME"; } // Don't inject auth into current thread; the current thread will obtain auth from its parent // NB: As topLevelThread = true, no further child threads will be created threads[i] = makeThread(prefix + "->child->Inherited_Auth_Child_" + i, false, false, expectAllThreadsToUseIdenticalAuthentication, false, expectedUsername); } } else { // The children being created are NOT expected to have security (ie not an InheritableThreadLocal OR auth was not injected into parent) for (int i = 0; i < threads.length; i++) { // Don't inject auth into current thread; neither current thread or child will have authentication // NB: As topLevelThread = true, no further child threads will be created threads[i] = makeThread(prefix + "->child->Unauth_Child_" + i, false, false, false, false, null); } } } // Start and execute the threads startAndRun(threads); } public static void main(String[] args) { junit.textui.TestRunner.run(SecurityContextHolderTests.class); } private Thread makeThread(final String threadIdentifier, final boolean topLevelThread, final boolean injectAuthIntoCurrentThread, final boolean expectAllThreadsToUseIdenticalAuthentication, final boolean expectChildrenToShareAuthenticationWithParent, final String expectedUsername) { final Random rnd = new Random(); Thread t = new Thread(new Runnable() { public void run() { if (injectAuthIntoCurrentThread) { // Set authentication in this thread SecurityContextHolder.getContext() .setAuthentication(new UsernamePasswordAuthenticationToken( expectedUsername, "pass")); //System.out.println(threadIdentifier + " - set to " + SecurityContextHolder.getContext().getAuthentication()); } else { //System.out.println(threadIdentifier + " - not set (currently " + SecurityContextHolder.getContext().getAuthentication() + ")"); } // Do some operations in current thread, checking authentication is as expected in the current thread (ie another thread doesn't change it) for (int i = 0; i < NUM_OPS; i++) { String currentUsername = (SecurityContextHolder.getContext().getAuthentication() == null) ? null : SecurityContextHolder.getContext().getAuthentication().getName(); if ((i % 7) == 0) { System.out.println(threadIdentifier + " at " + i + " username " + currentUsername); } try { TestCase.assertEquals("Failed on iteration " + i + "; Authentication was '" + currentUsername + "' but principal was expected to contain username '" + expectedUsername + "'", expectedUsername, currentUsername); } catch (ComparisonFailure err) { errors++; throw err; } try { Thread.sleep(rnd.nextInt(250)); } catch (InterruptedException ignore) {} } // Load some children threads, checking the authentication is as expected in the children (ie another thread doesn't change it) if (topLevelThread) { // Make four children, but we don't want the children to have any more children (so anti-nature, huh?) if (injectAuthIntoCurrentThread && expectChildrenToShareAuthenticationWithParent) { loadStartAndWaitForThreads(false, threadIdentifier, 4, expectAllThreadsToUseIdenticalAuthentication, true); } else { loadStartAndWaitForThreads(false, threadIdentifier, 4, expectAllThreadsToUseIdenticalAuthentication, false); } } } }, threadIdentifier); return t; } public final void setUp() throws Exception { SecurityContextHolder.setStrategyName(SecurityContextHolder.MODE_INHERITABLETHREADLOCAL); } private void startAndRun(Thread[] threads) { // Start them up for (int i = 0; i < threads.length; i++) { threads[i].start(); } // Wait for them to finish while (stillRunning(threads)) { try { Thread.sleep(250); } catch (InterruptedException ignore) {} } } private boolean stillRunning(Thread[] threads) { for (int i = 0; i < threads.length; i++) { if (threads[i].isAlive()) { return true; } } return false; } public void testContextHolderGetterSetterClearer() { SecurityContext sc = new SecurityContextImpl(); sc.setAuthentication(new UsernamePasswordAuthenticationToken("Foobar", "pass")); SecurityContextHolder.setContext(sc); assertEquals(sc, SecurityContextHolder.getContext()); SecurityContextHolder.clearContext(); assertNotSame(sc, SecurityContextHolder.getContext()); SecurityContextHolder.clearContext(); } public void testNeverReturnsNull() { assertNotNull(SecurityContextHolder.getContext()); SecurityContextHolder.clearContext(); } public void testRejectsNulls() { try { SecurityContextHolder.setContext(null); fail("Should have rejected null"); } catch (IllegalArgumentException expected) { assertTrue(true); } } public void testSynchronizationCustomStrategyLoading() { SecurityContextHolder.setStrategyName(InheritableThreadLocalSecurityContextHolderStrategy.class.getName()); assertTrue(new SecurityContextHolder().toString() .lastIndexOf("SecurityContextHolder[strategy='org.acegisecurity.context.InheritableThreadLocalSecurityContextHolderStrategy'") != -1); loadStartAndWaitForThreads(true, "Main_", NUM_THREADS, false, true); assertEquals("Thread errors detected; review log output for details", 0, errors); } public void testSynchronizationGlobal() throws Exception { SecurityContextHolder.clearContext(); SecurityContextHolder.setStrategyName(SecurityContextHolder.MODE_GLOBAL); loadStartAndWaitForThreads(true, "Main_", NUM_THREADS, true, false); assertEquals("Thread errors detected; review log output for details", 0, errors); } public void testSynchronizationInheritableThreadLocal() throws Exception { SecurityContextHolder.clearContext(); SecurityContextHolder.setStrategyName(SecurityContextHolder.MODE_INHERITABLETHREADLOCAL); loadStartAndWaitForThreads(true, "Main_", NUM_THREADS, false, true); assertEquals("Thread errors detected; review log output for details", 0, errors); } public void testSynchronizationThreadLocal() throws Exception { SecurityContextHolder.clearContext(); SecurityContextHolder.setStrategyName(SecurityContextHolder.MODE_THREADLOCAL); loadStartAndWaitForThreads(true, "Main_", NUM_THREADS, false, false); assertEquals("Thread errors detected; review log output for details", 0, errors); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -