Skip to content

Commit bc958f7

Browse files
author
nigel.zheng
committed
refactor: add AttachClaimsTestExecutionListener
1 parent 0fcc0de commit bc958f7

File tree

5 files changed

+101
-69
lines changed

5 files changed

+101
-69
lines changed
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package com.github.ahunigel.test.security;
2+
3+
import java.lang.annotation.*;
4+
5+
/**
6+
* Created by Nigel Zheng on 8/3/2018.
7+
* <p>
8+
* Attach claims as map to current authentication details
9+
*/
10+
@Target({ElementType.METHOD, ElementType.TYPE})
11+
@Retention(RetentionPolicy.RUNTIME)
12+
@Inherited
13+
@Documented
14+
public @interface AttachClaims {
15+
/**
16+
* Return the contained {@link Claim} annotations.
17+
*
18+
* @return the claims
19+
*/
20+
Claim[] value();
21+
22+
/**
23+
* key-value paired string array, redundant value will be ignored
24+
* <p>
25+
* would merge with #value() if key is absent
26+
*
27+
* @return
28+
*/
29+
String[] claims() default {};
30+
31+
}
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
package com.github.ahunigel.test.security;
2+
3+
import org.slf4j.Logger;
4+
import org.slf4j.LoggerFactory;
5+
import org.springframework.core.annotation.AnnotationUtils;
6+
import org.springframework.security.authentication.AbstractAuthenticationToken;
7+
import org.springframework.security.core.Authentication;
8+
import org.springframework.security.test.context.TestSecurityContextHolder;
9+
import org.springframework.test.context.TestContext;
10+
import org.springframework.test.context.support.AbstractTestExecutionListener;
11+
12+
import java.lang.reflect.AnnotatedElement;
13+
import java.util.Arrays;
14+
import java.util.HashMap;
15+
import java.util.Map;
16+
import java.util.stream.Collectors;
17+
18+
/**
19+
* Created by Nigel.Zheng on 8/3/2018.
20+
*/
21+
public class AttachClaimsTestExecutionListener extends AbstractTestExecutionListener {
22+
private static final Logger logger = LoggerFactory.getLogger(AttachClaimsTestExecutionListener.class);
23+
24+
@Override
25+
public void beforeTestClass(TestContext testContext) throws Exception {
26+
AttachClaims annotation = findAnnotation(testContext.getTestClass());
27+
28+
if (annotation != null) {
29+
attachClaimsToAuthentication(annotation);
30+
}
31+
}
32+
33+
@Override
34+
public void beforeTestMethod(TestContext testContext) throws Exception {
35+
AttachClaims annotation = findAnnotation(testContext.getTestMethod());
36+
37+
if (annotation != null) {
38+
attachClaimsToAuthentication(annotation);
39+
}
40+
}
41+
42+
private AttachClaims findAnnotation(AnnotatedElement annotated) {
43+
return AnnotationUtils.findAnnotation(annotated, AttachClaims.class);
44+
}
45+
46+
public void attachClaimsToAuthentication(AttachClaims annotation) {
47+
Authentication authentication = TestSecurityContextHolder.getContext().getAuthentication();
48+
if (authentication != null && authentication instanceof AbstractAuthenticationToken) {
49+
Map<String, String> claims = Arrays.stream(annotation.value()).collect(Collectors.toMap(Claim::name, Claim::value));
50+
Map<String, String> stringMap = toMap(annotation.claims());
51+
stringMap.entrySet().stream().forEach(entry -> claims.putIfAbsent(entry.getKey(), entry.getValue()));
52+
if (!claims.isEmpty()) {
53+
((AbstractAuthenticationToken) authentication).setDetails(claims);
54+
}
55+
} else {
56+
logger.warn("No authentication found, do not attach claims");
57+
}
58+
}
59+
60+
private Map<String, String> toMap(String[] claims) {
61+
final Map<String, String> map = new HashMap<>();
62+
for (int i = 0; i + 1 < claims.length; i += 2) {
63+
map.put(claims[i], claims[i + 1]);
64+
}
65+
return map;
66+
}
67+
}

src/main/java/com/github/ahunigel/test/security/Claim.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
@Target({ElementType.METHOD, ElementType.TYPE})
99
@Retention(RetentionPolicy.RUNTIME)
1010
@Documented
11-
@Repeatable(WithClaims.class)
11+
@Repeatable(AttachClaims.class)
1212
public @interface Claim {
1313

1414
String name();

src/main/java/com/github/ahunigel/test/security/WithClaims.java

Lines changed: 0 additions & 68 deletions
This file was deleted.
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
org.springframework.test.context.TestExecutionListener=\
2+
com.github.ahunigel.test.security.AttachClaimsTestExecutionListener

0 commit comments

Comments
 (0)