SEC-1431: Modify OpenID sample to use a custom UserDetailsService which allows any user to authenticate, allocating them a standard role and "registers" their ID in a map, allowing it to be retrieved in subsequent logins.
This commit is contained in:
parent
f5468087c2
commit
ee1fd1bc50
|
@ -4,10 +4,13 @@ apply plugin: 'war'
|
|||
apply plugin: 'jetty'
|
||||
|
||||
dependencies {
|
||||
compile project(':spring-security-core'),
|
||||
project(':spring-security-openid')
|
||||
|
||||
providedCompile 'javax.servlet:servlet-api:2.5@jar'
|
||||
|
||||
runtime project(':spring-security-web'),
|
||||
project(':spring-security-config'),
|
||||
project(':spring-security-openid'),
|
||||
project(':spring-security-taglibs'),
|
||||
'log4j:log4j:1.2.15@jar'
|
||||
}
|
|
@ -25,6 +25,11 @@
|
|||
<artifactId>spring-security-web</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-taglibs</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-openid</artifactId>
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
package org.springframework.security.samples.openid;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.core.userdetails.User;
|
||||
|
||||
/**
|
||||
* Customized {@code UserDetails} implementation.
|
||||
*
|
||||
* @author Luke Taylor
|
||||
* @since 3.1
|
||||
*/
|
||||
public class CustomUserDetails extends User {
|
||||
private String email;
|
||||
private String name;
|
||||
private boolean newUser;
|
||||
|
||||
public CustomUserDetails(String username, Collection<GrantedAuthority> authorities) {
|
||||
super(username, "unused", authorities);
|
||||
}
|
||||
|
||||
public String getEmail() {
|
||||
return email;
|
||||
}
|
||||
|
||||
public void setEmail(String email) {
|
||||
this.email = email;
|
||||
}
|
||||
|
||||
public boolean isNewUser() {
|
||||
return newUser;
|
||||
}
|
||||
|
||||
public void setNewUser(boolean newUser) {
|
||||
this.newUser = newUser;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,103 @@
|
|||
package org.springframework.security.samples.openid;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.core.authority.AuthorityUtils;
|
||||
import org.springframework.security.core.userdetails.AuthenticationUserDetailsService;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||
import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
||||
import org.springframework.security.openid.OpenIDAttribute;
|
||||
import org.springframework.security.openid.OpenIDAuthenticationToken;
|
||||
|
||||
/**
|
||||
* Custom UserDetailsService which accepts any OpenID user, "registering" new users in a map so they can be welcomed
|
||||
* back to the site on subsequent logins.
|
||||
*
|
||||
* @author Luke Taylor
|
||||
* @since 3.1
|
||||
*/
|
||||
public class CustomUserDetailsService implements UserDetailsService, AuthenticationUserDetailsService<OpenIDAuthenticationToken> {
|
||||
|
||||
private Map<String, CustomUserDetails> registeredUsers = new HashMap<String, CustomUserDetails>();
|
||||
|
||||
private static final List<GrantedAuthority> DEFAULT_AUTHORITIES = AuthorityUtils.createAuthorityList("ROLE_USER");
|
||||
|
||||
/**
|
||||
* Implementation of {@code UserDetailsService}. We only need this to satisfy the {@code RememberMeServices}
|
||||
* requirements.
|
||||
*/
|
||||
public UserDetails loadUserByUsername(String id) throws UsernameNotFoundException {
|
||||
UserDetails user = registeredUsers.get(id);
|
||||
|
||||
if (user == null) {
|
||||
throw new UsernameNotFoundException(id);
|
||||
}
|
||||
|
||||
return user;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of {@code AuthenticationUserDetailsService} which allows full access to the submitted
|
||||
* {@code Authentication} object. Used by the OpenIDAuthenticationProvider.
|
||||
*/
|
||||
public UserDetails loadUserDetails(OpenIDAuthenticationToken token) {
|
||||
String id = token.getIdentityUrl();
|
||||
|
||||
CustomUserDetails user = registeredUsers.get(id);
|
||||
|
||||
if (user != null) {
|
||||
return user;
|
||||
}
|
||||
|
||||
String email = null;
|
||||
String firstName = null;
|
||||
String lastName = null;
|
||||
String fullName = null;
|
||||
|
||||
List<OpenIDAttribute> attributes = token.getAttributes();
|
||||
|
||||
for (OpenIDAttribute attribute : attributes) {
|
||||
if (attribute.getName().equals("email")) {
|
||||
email = attribute.getValues().get(0);
|
||||
}
|
||||
|
||||
if (attribute.getName().equals("firstname")) {
|
||||
firstName = attribute.getValues().get(0);
|
||||
}
|
||||
|
||||
if (attribute.getName().equals("fullname")) {
|
||||
fullName = attribute.getValues().get(0);
|
||||
}
|
||||
}
|
||||
|
||||
if (fullName == null) {
|
||||
StringBuilder fullNameBldr = new StringBuilder();
|
||||
|
||||
if (firstName != null) {
|
||||
fullNameBldr.append(firstName);
|
||||
}
|
||||
|
||||
if (lastName != null) {
|
||||
fullNameBldr.append(" ").append(lastName);
|
||||
}
|
||||
fullName = fullNameBldr.toString();
|
||||
}
|
||||
|
||||
user = new CustomUserDetails(id, DEFAULT_AUTHORITIES);
|
||||
user.setEmail(email);
|
||||
user.setName(fullName);
|
||||
|
||||
registeredUsers.put(id, user);
|
||||
|
||||
user = new CustomUserDetails(id, DEFAULT_AUTHORITIES);
|
||||
user.setEmail(email);
|
||||
user.setName(fullName);
|
||||
user.setNewUser(true);
|
||||
|
||||
return user;
|
||||
}
|
||||
}
|
|
@ -1,6 +0,0 @@
|
|||
package zzz;
|
||||
/**
|
||||
* @author Luke Taylor
|
||||
*/
|
||||
public class Dummy {
|
||||
}
|
|
@ -14,10 +14,13 @@
|
|||
<intercept-url pattern="/**" access="ROLE_USER"/>
|
||||
<intercept-url pattern="/openidlogin.jsp*" filters="none"/>
|
||||
<logout/>
|
||||
<openid-login login-page="/openidlogin.jsp" authentication-failure-url="/openidlogin.jsp?login_error=true">
|
||||
<openid-login login-page="/openidlogin.jsp" user-service-ref="registeringUserService"
|
||||
authentication-failure-url="/openidlogin.jsp?login_error=true">
|
||||
<attribute-exchange>
|
||||
<openid-attribute name="email" type="http://schema.openid.net/contact/email" required="true" count="2"/>
|
||||
<openid-attribute name="name" type="http://schema.openid.net/namePerson/friendly" />
|
||||
<openid-attribute name="email" type="http://axschema.org/contact/email" required="true" count="1"/>
|
||||
<openid-attribute name="firstname" type="http://axschema.org/namePerson/first" />
|
||||
<openid-attribute name="lastname" type="http://axschema.org/namePerson/last" />
|
||||
<openid-attribute name="fullname" type="http://axschema.org/namePerson" />
|
||||
</attribute-exchange>
|
||||
</openid-login>
|
||||
<remember-me token-repository-ref="tokenRepo"/>
|
||||
|
@ -28,11 +31,13 @@
|
|||
|
||||
<authentication-manager alias="authenticationManager"/>
|
||||
|
||||
<b:bean id="registeringUserService" class="org.springframework.security.samples.openid.CustomUserDetailsService" />
|
||||
<!--
|
||||
<user-service id="userService">
|
||||
<user name="http://luke.taylor.myopenid.com/" authorities="ROLE_SUPERVISOR,ROLE_USER" />
|
||||
<user name="http://luke.taylor.openid.cn/" authorities="ROLE_SUPERVISOR,ROLE_USER" />
|
||||
<user name="http://raykrueger.blogspot.com/" authorities="ROLE_SUPERVISOR,ROLE_USER" />
|
||||
<user name="http://spring.security.test.myopenid.com/" authorities="ROLE_SUPERVISOR,ROLE_USER" />
|
||||
</user-service>
|
||||
|
||||
-->
|
||||
</b:beans>
|
||||
|
|
|
@ -1,11 +1,26 @@
|
|||
<%@ taglib prefix="c" uri="http://java.sun.com/jstl/core_rt"%>
|
||||
<%@ taglib prefix="sec" uri="http://www.springframework.org/security/tags" %>
|
||||
|
||||
<html>
|
||||
<body>
|
||||
<h1>Home Page</h1>
|
||||
<p>Anyone can view this page.</p>
|
||||
|
||||
<p>Your principal object is....: <%= request.getUserPrincipal() %></p>
|
||||
<h1>OpenID Sample Home Page</h1>
|
||||
|
||||
<p><a href="secure/index.jsp">Secure page</a></p>
|
||||
<p><a href="secure/extreme/index.jsp">Extremely secure page</a></p>
|
||||
<sec:authentication property='principal.newUser' var='isNew' />
|
||||
<p>
|
||||
Welcome<c:if test="${!isNew}"> back,</c:if> <sec:authentication property='principal.name' />!
|
||||
</p>
|
||||
<c:if test="${isNew}">
|
||||
<p>
|
||||
As a first time user of this site, your OpenID identity has been registered
|
||||
by the application and will be recognized if you return.
|
||||
</p>
|
||||
</c:if>
|
||||
|
||||
<h3>Technical Information</h3>
|
||||
<p>
|
||||
Your principal object is....: <%= request.getUserPrincipal() %>
|
||||
</p>
|
||||
<p><a href="j_spring_security_logout">Logout</a>
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
||||
|
|
|
@ -1,9 +0,0 @@
|
|||
<html>
|
||||
<body>
|
||||
<h1>VERY Secure Page</h1>
|
||||
This is a protected page. You can only see me if you are a supervisor.
|
||||
|
||||
<p><a href="../../">Home</a>
|
||||
<p><a href="../../j_spring_security_logout">Logout</a>
|
||||
</body>
|
||||
</html>
|
|
@ -1,15 +0,0 @@
|
|||
<html>
|
||||
<body>
|
||||
<h1>Secure Page</h1>
|
||||
This is a protected page. You can get to me if you've been remembered,
|
||||
or if you've authenticated this session.<br><br>
|
||||
|
||||
<%if (request.isUserInRole("ROLE_SUPERVISOR")) { %>
|
||||
You are a supervisor! You can therefore see the <a href="extreme/index.jsp">extremely secure page</a>.<br><br>
|
||||
<% } %>
|
||||
|
||||
|
||||
<p><a href="../">Home</a>
|
||||
<p><a href="../j_spring_security_logout">Logout</a>
|
||||
</body>
|
||||
</html>
|
|
@ -30,7 +30,7 @@ or if you've authenticated this session.
|
|||
</table>
|
||||
|
||||
|
||||
<p><a href="../">Home</a>
|
||||
<p><a href="../j_spring_security_logout">Logout</a>
|
||||
<p><a href="../">Home</a></p>
|
||||
<p><a href="../j_spring_security_logout">Logout</a></p>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -204,6 +204,13 @@ public abstract class AbstractPreAuthenticatedProcessingFilter extends GenericFi
|
|||
this.authenticationManager = authenticationManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* If set to {@code true}, any {@code AuthenticationException} raised by the {@code AuthenticationManager} will be
|
||||
* swallowed, and the request will be allowed to proceed, potentially using alternative authentication mechanisms.
|
||||
* If {@code false} (the default), authentication failure will result in an immediate exception.
|
||||
*
|
||||
* @param shouldContinue set to {@code true} to allow the request to proceed after a failed authentication.
|
||||
*/
|
||||
public void setContinueFilterChainOnUnsuccessfulAuthentication(boolean shouldContinue) {
|
||||
continueFilterChainOnUnsuccessfulAuthentication = shouldContinue;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue