mirror of
https://github.com/spring-projects/spring-security.git
synced 2025-07-06 02:32:14 +00:00
Treat URLs as String before equals/hashcode
java.net.URL performs DNS lookups whenever its equals/hashCode is used. Thus attribute values of type java.net.URL need to be converted to something else before they are used for equals/hashCode. Closes gh-10673
This commit is contained in:
parent
e28fcbfbbe
commit
ca0a6d9777
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2002-2017 the original author or authors.
|
* Copyright 2002-2022 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@ -16,9 +16,11 @@
|
|||||||
|
|
||||||
package org.springframework.security.oauth2.core.user;
|
package org.springframework.security.oauth2.core.user;
|
||||||
|
|
||||||
|
import java.net.URL;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
import org.springframework.security.core.GrantedAuthority;
|
import org.springframework.security.core.GrantedAuthority;
|
||||||
import org.springframework.security.core.SpringSecurityCoreVersion;
|
import org.springframework.security.core.SpringSecurityCoreVersion;
|
||||||
@ -85,13 +87,37 @@ public class OAuth2UserAuthority implements GrantedAuthority {
|
|||||||
if (!this.getAuthority().equals(that.getAuthority())) {
|
if (!this.getAuthority().equals(that.getAuthority())) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return this.getAttributes().equals(that.getAttributes());
|
Map<String, Object> thatAttributes = that.getAttributes();
|
||||||
|
if (getAttributes().size() != thatAttributes.size()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
for (Map.Entry<String, Object> e : getAttributes().entrySet()) {
|
||||||
|
String key = e.getKey();
|
||||||
|
Object value = convertURLIfNecessary(e.getValue());
|
||||||
|
if (value == null) {
|
||||||
|
if (!(thatAttributes.get(key) == null && thatAttributes.containsKey(key))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Object thatValue = convertURLIfNecessary(thatAttributes.get(key));
|
||||||
|
if (!value.equals(thatValue)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
int result = this.getAuthority().hashCode();
|
int result = this.getAuthority().hashCode();
|
||||||
result = 31 * result + this.getAttributes().hashCode();
|
result = 31 * result;
|
||||||
|
for (Map.Entry<String, Object> e : getAttributes().entrySet()) {
|
||||||
|
Object key = e.getKey();
|
||||||
|
Object value = convertURLIfNecessary(e.getValue());
|
||||||
|
result += Objects.hashCode(key) ^ Objects.hashCode(value);
|
||||||
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -100,4 +126,12 @@ public class OAuth2UserAuthority implements GrantedAuthority {
|
|||||||
return this.getAuthority();
|
return this.getAuthority();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return {@code URL} converted to a string since {@code URL} shouldn't be used for
|
||||||
|
* equality/hashCode. For other instances the value is returned as is.
|
||||||
|
*/
|
||||||
|
private static Object convertURLIfNecessary(Object value) {
|
||||||
|
return (value instanceof URL) ? ((URL) value).toExternalForm() : value;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2002-2017 the original author or authors.
|
* Copyright 2002-2022 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@ -16,6 +16,8 @@
|
|||||||
|
|
||||||
package org.springframework.security.oauth2.core.user;
|
package org.springframework.security.oauth2.core.user;
|
||||||
|
|
||||||
|
import java.net.MalformedURLException;
|
||||||
|
import java.net.URL;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
@ -35,6 +37,22 @@ public class OAuth2UserAuthorityTests {
|
|||||||
|
|
||||||
private static final Map<String, Object> ATTRIBUTES = Collections.singletonMap("username", "test");
|
private static final Map<String, Object> ATTRIBUTES = Collections.singletonMap("username", "test");
|
||||||
|
|
||||||
|
private static final OAuth2UserAuthority AUTHORITY_WITH_OBJECTURL;
|
||||||
|
|
||||||
|
private static final OAuth2UserAuthority AUTHORITY_WITH_STRINGURL;
|
||||||
|
|
||||||
|
static {
|
||||||
|
try {
|
||||||
|
AUTHORITY_WITH_OBJECTURL = new OAuth2UserAuthority(
|
||||||
|
Collections.singletonMap("someurl", new URL("https://localhost")));
|
||||||
|
AUTHORITY_WITH_STRINGURL = new OAuth2UserAuthority(
|
||||||
|
Collections.singletonMap("someurl", "https://localhost"));
|
||||||
|
}
|
||||||
|
catch (MalformedURLException ex) {
|
||||||
|
throw new RuntimeException(ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void constructorWhenAuthorityIsNullThenThrowIllegalArgumentException() {
|
public void constructorWhenAuthorityIsNullThenThrowIllegalArgumentException() {
|
||||||
assertThatIllegalArgumentException().isThrownBy(() -> new OAuth2UserAuthority(null, ATTRIBUTES));
|
assertThatIllegalArgumentException().isThrownBy(() -> new OAuth2UserAuthority(null, ATTRIBUTES));
|
||||||
@ -58,4 +76,22 @@ public class OAuth2UserAuthorityTests {
|
|||||||
assertThat(userAuthority.getAttributes()).isEqualTo(ATTRIBUTES);
|
assertThat(userAuthority.getAttributes()).isEqualTo(ATTRIBUTES);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void equalsRegardlessOfUrlType() {
|
||||||
|
assertThat(AUTHORITY_WITH_OBJECTURL).isEqualTo(AUTHORITY_WITH_OBJECTURL);
|
||||||
|
assertThat(AUTHORITY_WITH_STRINGURL).isEqualTo(AUTHORITY_WITH_STRINGURL);
|
||||||
|
|
||||||
|
assertThat(AUTHORITY_WITH_OBJECTURL).isEqualTo(AUTHORITY_WITH_STRINGURL);
|
||||||
|
assertThat(AUTHORITY_WITH_STRINGURL).isEqualTo(AUTHORITY_WITH_OBJECTURL);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void hashCodeIsSameRegardlessOfUrlType() {
|
||||||
|
assertThat(AUTHORITY_WITH_OBJECTURL.hashCode()).isEqualTo(AUTHORITY_WITH_OBJECTURL.hashCode());
|
||||||
|
assertThat(AUTHORITY_WITH_STRINGURL.hashCode()).isEqualTo(AUTHORITY_WITH_STRINGURL.hashCode());
|
||||||
|
|
||||||
|
assertThat(AUTHORITY_WITH_OBJECTURL.hashCode()).isEqualTo(AUTHORITY_WITH_STRINGURL.hashCode());
|
||||||
|
assertThat(AUTHORITY_WITH_STRINGURL.hashCode()).isEqualTo(AUTHORITY_WITH_OBJECTURL.hashCode());
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user