10 changed files with 137 additions and 426 deletions
@ -0,0 +1,52 @@ |
|||||||
|
package org.springframework.security.providers; |
||||||
|
|
||||||
|
import org.springframework.security.AuthenticationException; |
||||||
|
import org.springframework.security.userdetails.UserDetails; |
||||||
|
|
||||||
|
/** |
||||||
|
* Populates the <code>UserDetails</code> associated with a CAS authenticated |
||||||
|
* user. |
||||||
|
* |
||||||
|
* <p> |
||||||
|
* Intended to grant authorities (roles) for providers that do not support |
||||||
|
* authorities/roles directly. It merely authenticates their identity. |
||||||
|
* As Spring Security needs to know the authorities granted to a user in |
||||||
|
* order to construct a valid <code>Authentication</code> object, implementations |
||||||
|
* of this interface will provide this information. |
||||||
|
* </p> |
||||||
|
* |
||||||
|
* <p> |
||||||
|
* A {@link UserDetails} is returned by implementations. The |
||||||
|
* <code>UserDetails</code> must, at minimum, contain the username and |
||||||
|
* <code>GrantedAuthority[]</code> objects applicable to the authenticated |
||||||
|
* user. Note that Spring Security ignores the password and enabled/disabled |
||||||
|
* status of the <code>UserDetails</code> because this is |
||||||
|
* authentication-related and should have been enforced by another provider server. The |
||||||
|
* <code>UserDetails</code> returned by implementations is stored in the |
||||||
|
* generated <code>AuthenticationToken</code>, so additional properties |
||||||
|
* such as email addresses, telephone numbers etc can easily be stored. |
||||||
|
* </p> |
||||||
|
* |
||||||
|
* <p> |
||||||
|
* Implementations should not perform any caching. They will only be called |
||||||
|
* when a refresh is required. |
||||||
|
* </p> |
||||||
|
* |
||||||
|
* @author Ben Alex |
||||||
|
* @author Ray Krueger |
||||||
|
* @version $Id$ |
||||||
|
*/ |
||||||
|
public interface AuthoritiesPopulator { |
||||||
|
/** |
||||||
|
* Obtains the granted authorities for the specified user.<P>May throw any |
||||||
|
* <code>AuthenticationException</code> or return <code>null</code> if the authorities are unavailable.</p> |
||||||
|
* |
||||||
|
* @param casUserId as obtained from the CAS validation service |
||||||
|
* |
||||||
|
* @return the details of the indicated user (at minimum the granted authorities and the username) |
||||||
|
* |
||||||
|
* @throws org.springframework.security.AuthenticationException DOCUMENT ME! |
||||||
|
*/ |
||||||
|
UserDetails getUserDetails(String casUserId) |
||||||
|
throws AuthenticationException; |
||||||
|
} |
||||||
@ -0,0 +1,40 @@ |
|||||||
|
package org.springframework.security.providers; |
||||||
|
|
||||||
|
import org.springframework.beans.factory.InitializingBean; |
||||||
|
import org.springframework.security.AuthenticationException; |
||||||
|
import org.springframework.security.userdetails.UserDetails; |
||||||
|
import org.springframework.security.userdetails.UserDetailsService; |
||||||
|
import org.springframework.util.Assert; |
||||||
|
|
||||||
|
/** |
||||||
|
* Populates the CAS authorities via an {@link org.springframework.security.userdetails.UserDetailsService}.<P>The additional information (username, |
||||||
|
* password, enabled status etc) an <code>AuthenticationDao</code> implementation provides about a <code>User</code> |
||||||
|
* is ignored. Only the <code>GrantedAuthority</code>s are relevant to this class.</p> |
||||||
|
* |
||||||
|
* @author Ben Alex |
||||||
|
* @version $Id$ |
||||||
|
*/ |
||||||
|
public class DaoAuthoritiesPopulator implements AuthoritiesPopulator, InitializingBean { |
||||||
|
//~ Instance fields ================================================================================================
|
||||||
|
|
||||||
|
private UserDetailsService userDetailsService; |
||||||
|
|
||||||
|
//~ Methods ========================================================================================================
|
||||||
|
|
||||||
|
public void afterPropertiesSet() throws Exception { |
||||||
|
Assert.notNull(this.userDetailsService, "A UserDetailsService must be set"); |
||||||
|
} |
||||||
|
|
||||||
|
public UserDetails getUserDetails(String casUserId) |
||||||
|
throws AuthenticationException { |
||||||
|
return this.userDetailsService.loadUserByUsername(casUserId); |
||||||
|
} |
||||||
|
|
||||||
|
public UserDetailsService getUserDetailsService() { |
||||||
|
return userDetailsService; |
||||||
|
} |
||||||
|
|
||||||
|
public void setUserDetailsService(UserDetailsService userDetailsService) { |
||||||
|
this.userDetailsService = userDetailsService; |
||||||
|
} |
||||||
|
} |
||||||
@ -1,201 +0,0 @@ |
|||||||
/* 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.springframework.security.ui.openid.consumers; |
|
||||||
|
|
||||||
import com.janrain.openid.consumer.AuthRequest; |
|
||||||
import com.janrain.openid.consumer.Consumer; |
|
||||||
import com.janrain.openid.consumer.ErrorResponse; |
|
||||||
import com.janrain.openid.consumer.Response; |
|
||||||
import com.janrain.openid.consumer.StatusCode; |
|
||||||
import com.janrain.openid.store.OpenIDStore; |
|
||||||
|
|
||||||
import org.springframework.security.providers.openid.OpenIDAuthenticationStatus; |
|
||||||
import org.springframework.security.providers.openid.OpenIDAuthenticationToken; |
|
||||||
|
|
||||||
import org.springframework.security.ui.openid.OpenIDConstants; |
|
||||||
import org.springframework.security.ui.openid.OpenIDConsumer; |
|
||||||
import org.springframework.security.ui.openid.OpenIDConsumerException; |
|
||||||
|
|
||||||
import org.springframework.beans.factory.InitializingBean; |
|
||||||
|
|
||||||
import org.springframework.util.Assert; |
|
||||||
|
|
||||||
import java.io.IOException; |
|
||||||
|
|
||||||
import java.util.HashMap; |
|
||||||
import java.util.Map; |
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest; |
|
||||||
import javax.servlet.http.HttpSession; |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* OpenIDConsumer implementation using the JanRain OpenID library |
|
||||||
* |
|
||||||
* @author Robin Bramley, Opsera Ltd |
|
||||||
* @version $Id:$ |
|
||||||
*/ |
|
||||||
public class JanRainOpenIDConsumer implements OpenIDConsumer, InitializingBean { |
|
||||||
//~ Static fields/initializers =====================================================================================
|
|
||||||
|
|
||||||
private static final String SAVED_ID_SESSION_KEY = "savedId"; |
|
||||||
|
|
||||||
//~ Instance fields ================================================================================================
|
|
||||||
|
|
||||||
private OpenIDStore store; |
|
||||||
private String returnToUrl = "j_spring_openid_security_check"; |
|
||||||
|
|
||||||
//~ Methods ========================================================================================================
|
|
||||||
|
|
||||||
public void afterPropertiesSet() throws Exception { |
|
||||||
Assert.notNull(this.store, "An OpenIDStore must be set on the store property"); |
|
||||||
} |
|
||||||
|
|
||||||
/* (non-Javadoc) |
|
||||||
* @see org.springframework.security.ui.openid.OpenIDConsumer#beginConsumption(java.lang.String) |
|
||||||
*/ |
|
||||||
public String beginConsumption(HttpServletRequest req, String identityUrl, String returnToUrl) |
|
||||||
throws OpenIDConsumerException { |
|
||||||
// fetch/create a session Map for the consumer's use
|
|
||||||
HttpSession session = req.getSession(); |
|
||||||
Map sessionMap = (Map) session.getAttribute(OpenIDConstants.OPENID_SESSION_MAP_KEY); |
|
||||||
|
|
||||||
if (sessionMap == null) { |
|
||||||
sessionMap = new HashMap(); |
|
||||||
session.setAttribute(OpenIDConstants.OPENID_SESSION_MAP_KEY, sessionMap); |
|
||||||
} |
|
||||||
|
|
||||||
Consumer openIdConsumer = new Consumer(sessionMap, store); |
|
||||||
|
|
||||||
// Create an Authrequest object from the submitted value
|
|
||||||
AuthRequest ar; |
|
||||||
|
|
||||||
try { |
|
||||||
ar = openIdConsumer.begin(identityUrl); |
|
||||||
} catch (IOException ioe) { |
|
||||||
req.getSession().setAttribute(SAVED_ID_SESSION_KEY, escapeAttr(identityUrl)); |
|
||||||
throw new OpenIDConsumerException("Error on begin consumption for " + identityUrl, ioe); |
|
||||||
} |
|
||||||
|
|
||||||
// construct trust root and return to URLs.
|
|
||||||
String port = ""; |
|
||||||
|
|
||||||
if (req.getServerPort() != 80) { |
|
||||||
port = ":" + req.getServerPort(); |
|
||||||
} |
|
||||||
|
|
||||||
String trustRoot = req.getScheme() + "://" + req.getServerName() + port + "/"; |
|
||||||
String cp = req.getContextPath(); |
|
||||||
|
|
||||||
if (!cp.equals("")) { |
|
||||||
cp = cp.substring(1) + "/"; |
|
||||||
} |
|
||||||
|
|
||||||
String returnTo = trustRoot + cp + this.returnToUrl; |
|
||||||
|
|
||||||
// send the user the redirect url to proceed with OpenID authentication
|
|
||||||
return ar.redirectUrl(trustRoot, returnTo); |
|
||||||
} |
|
||||||
|
|
||||||
/* (non-Javadoc) |
|
||||||
* @see org.springframework.security.ui.openid.OpenIDConsumer#endConsumption(javax.servlet.http.HttpServletRequest) |
|
||||||
*/ |
|
||||||
public OpenIDAuthenticationToken endConsumption(HttpServletRequest req) |
|
||||||
throws OpenIDConsumerException { |
|
||||||
HttpSession session = req.getSession(); |
|
||||||
Map sessionMap = (Map) session.getAttribute(OpenIDConstants.OPENID_SESSION_MAP_KEY); |
|
||||||
|
|
||||||
if (sessionMap == null) { |
|
||||||
sessionMap = new HashMap(); |
|
||||||
session.setAttribute(OpenIDConstants.OPENID_SESSION_MAP_KEY, sessionMap); |
|
||||||
} |
|
||||||
|
|
||||||
// get a Consumer instance
|
|
||||||
Consumer openIdConsumer = new Consumer(sessionMap, store); |
|
||||||
|
|
||||||
// convert the argument map into the form the library uses with a handy
|
|
||||||
// convenience function
|
|
||||||
Map query = Consumer.filterArgs(req.getParameterMap()); |
|
||||||
|
|
||||||
// Check the arguments to see what the response was.
|
|
||||||
Response response = openIdConsumer.complete(query); |
|
||||||
|
|
||||||
String message = ""; |
|
||||||
OpenIDAuthenticationStatus status; |
|
||||||
|
|
||||||
StatusCode statusCode = response.getStatus(); |
|
||||||
|
|
||||||
if (statusCode == StatusCode.CANCELLED) { |
|
||||||
status = OpenIDAuthenticationStatus.CANCELLED; |
|
||||||
} else if (statusCode == StatusCode.ERROR) { |
|
||||||
status = OpenIDAuthenticationStatus.ERROR; |
|
||||||
message = ((ErrorResponse) response).getMessage(); |
|
||||||
} else if (statusCode == StatusCode.FAILURE) { |
|
||||||
status = OpenIDAuthenticationStatus.FAILURE; |
|
||||||
} else if (statusCode == StatusCode.SETUP_NEEDED) { |
|
||||||
status = OpenIDAuthenticationStatus.SETUP_NEEDED; |
|
||||||
} else if (statusCode == StatusCode.SUCCESS) { |
|
||||||
status = OpenIDAuthenticationStatus.SUCCESS; |
|
||||||
} else { |
|
||||||
// unknown status code
|
|
||||||
throw new OpenIDConsumerException("Unknown response status " + statusCode.toString()); |
|
||||||
} |
|
||||||
|
|
||||||
return new OpenIDAuthenticationToken(status, response.getIdentityUrl(), message); |
|
||||||
} |
|
||||||
|
|
||||||
/* |
|
||||||
* This method escapes characters in a string that can cause problems in |
|
||||||
* HTML |
|
||||||
*/ |
|
||||||
private String escapeAttr(String s) { |
|
||||||
if (s == null) { |
|
||||||
return ""; |
|
||||||
} |
|
||||||
|
|
||||||
StringBuffer result = new StringBuffer(); |
|
||||||
|
|
||||||
for (int i = 0; i < s.length(); i++) { |
|
||||||
char c = s.charAt(i); |
|
||||||
|
|
||||||
if (c == '<') { |
|
||||||
result.append("<"); |
|
||||||
} else if (c == '>') { |
|
||||||
result.append(">"); |
|
||||||
} else if (c == '&') { |
|
||||||
result.append("&"); |
|
||||||
} else if (c == '\"') { |
|
||||||
result.append("""); |
|
||||||
} else if (c == '\'') { |
|
||||||
result.append("'"); |
|
||||||
} else if (c == '\\') { |
|
||||||
result.append("\"); |
|
||||||
} else { |
|
||||||
result.append(c); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
return result.toString(); |
|
||||||
} |
|
||||||
|
|
||||||
public void setReturnToUrl(String returnToUrl) { |
|
||||||
this.returnToUrl = returnToUrl; |
|
||||||
} |
|
||||||
|
|
||||||
// dependency injection
|
|
||||||
public void setStore(OpenIDStore store) { |
|
||||||
this.store = store; |
|
||||||
} |
|
||||||
} |
|
||||||
Loading…
Reference in new issue