Commit 28aca081 authored by Gradl, Tobias's avatar Gradl, Tobias
Browse files

700: Migrate from old SP libraries to consolidated version

Task-Url: https://minfba.de.dariah.eu/mantisbt/view.php?id=700
parent bd14ce93
......@@ -2,6 +2,7 @@ package de.dariah.aai.javasp.base;
import java.util.Collection;
import org.joda.time.DateTime;
import org.springframework.security.core.userdetails.UserDetails;
public class SimpleUserDetails implements UserDetails, StagedUserDetails {
......@@ -16,6 +17,7 @@ public class SimpleUserDetails implements UserDetails, StagedUserDetails {
private boolean expired;
private String language;
private boolean hasAllAttributes;
private DateTime lastLogin;
public SimpleUserDetails() {}
......@@ -52,6 +54,9 @@ public class SimpleUserDetails implements UserDetails, StagedUserDetails {
public void setAuthorities(Collection<Role> authorities) { this.authorities = authorities; }
public void setUsername(String username) { this.username = username; }
public DateTime getLastLogin() { return lastLogin; }
public void setLastLogin(DateTime lastLogin) { this.lastLogin = lastLogin; }
public String getUsername() { return username; }
public String getPassword() { return ""; }
public Collection<Role> getAuthorities() { return authorities; }
......
package de.dariah.aai.javasp.service;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import de.dariah.aai.javasp.base.PersistedUserDetails;
public interface PersistedUserDetailsService {
public PersistedUserDetails loadUserByUsername(String domain, String username) throws UsernameNotFoundException;
public void saveUser(PersistedUserDetails persistedUser);
}
# dariahsp
\ No newline at end of file
# dariahsp
This library contains a wrapper for Spring Security SAML, along with extensions useful particularly for the context of DARIAH-DE. Fundamentally, this library distinguishes two authentication methods: the *local* method is intended primarily for developer and test setups, the *saml* method is targeted towards production environments.
## Authentication methods
### Local
To support local authentication, configure this library as in the *security-local-context.xml* template. To complete the setup for this method, applications might want to implement the *UserService* interface (base implementation *BaseUserService*) to provide access to persisted user information.
The implementation needs to be provided to the *LocalAuthenticationProvider*.
In cases that do not require user detail persistence, no implementation of the *UserDetails* should be provided to the *LocalAuthenticationProvider*.
### SAML
\ No newline at end of file
......@@ -15,14 +15,15 @@
<eu.dariah.de.minfba.core-metamodel.version>3.3.0-SNAPSHOT</eu.dariah.de.minfba.core-metamodel.version>
<!-- Required? <org.springframework-version>4.3.6.RELEASE</org.springframework-version>
<org.springsecurity-version>4.2.1.RELEASE</org.springsecurity-version> -->
<org.springframework-version>4.3.6.RELEASE</org.springframework-version>
<!-- Required? <org.springsecurity-version>4.2.1.RELEASE</org.springsecurity-version> -->
<spring-security-saml2-core.version>1.0.3-SNAPSHOT</spring-security-saml2-core.version>
<joda-time-version>2.9.2</joda-time-version>
</properties>
<dependencies>
<dependency>
<groupId>eu.dariah.de.minfba.core</groupId>
......@@ -32,9 +33,14 @@
<dependency>
<groupId>eu.dariah.eu</groupId>
<artifactId>spring-security-saml2-core</artifactId>
<version>1.0.3-SNAPSHOT</version>
<version>${spring-security-saml2-core.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${org.springframework-version}</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
......@@ -43,6 +49,11 @@
<scope>provided</scope>
</dependency>
<dependency>
<groupId>joda-time</groupId>
<artifactId>joda-time</artifactId>
<version>${joda-time-version}</version>
</dependency>
</dependencies>
......
package eu.dariah.de.dariahsp.model;
public class RoleImpl implements Role {
private static final long serialVersionUID = 4139022217963525795L;
private int level;
private String authority;
private String description;
public RoleImpl() {}
public RoleImpl(String authority) {
this.authority = authority;
}
@Override public int getLevel() { return level; }
public void setLevel(int level) { this.level = level; }
@Override public String getAuthority() { return authority; }
public void setAuthority(String authority) { this.authority = authority; }
@Override public String getDescription() { return description; }
public void setDescription(String description) { this.description = description; }
@Override public int getId() { return 0; }
}
package eu.dariah.de.dariahsp.model;
public interface StagedUserDetails {
public int getMaxAuthorityLevel();
public boolean isAuthorized(Role compRole);
}
package eu.dariah.de.dariahsp.model;
public interface User {
import java.util.Collection;
import org.joda.time.DateTime;
import org.springframework.security.core.userdetails.UserDetails;
import eu.dariah.de.minfba.core.metamodel.interfaces.Identifiable;
public interface User extends UserDetails, Identifiable {
public String getId();
public String getNameId();
......@@ -10,4 +17,14 @@ public interface User {
public String getEndpointName();
public String getLanguage();
public int getMaxAuthorityLevel();
public boolean isAuthorized(Role compRole);
public void setEndpointId(String localDomain);
public void setEndpointName(String defaultLocalDomain);
public void setHasAllAttributes(boolean b);
public void setAuthorities(Collection<Role> roles);
public void setUsername(String username);
public void setExpired(boolean b);
public void setLastLogin(DateTime now);
}
......@@ -2,9 +2,9 @@ package eu.dariah.de.dariahsp.model;
import java.util.Collection;
import org.springframework.security.core.userdetails.UserDetails;
import org.joda.time.DateTime;
public class SimpleUserDetails implements UserDetails, StagedUserDetails {
public class UserImpl implements User {
private static final long serialVersionUID = -1504226378983075730L;
private Collection<Role> authorities;
......@@ -16,10 +16,11 @@ public class SimpleUserDetails implements UserDetails, StagedUserDetails {
private boolean expired;
private String language;
private boolean hasAllAttributes;
public SimpleUserDetails() {}
private DateTime lastLogin;
public UserImpl() {}
public SimpleUserDetails(User user, Collection<Role> authorities) {
public UserImpl(User user, Collection<Role> authorities) {
this.id = user.getId();
this.username = user.getNameId();
this.expired = user.isExpired();
......@@ -52,15 +53,19 @@ public class SimpleUserDetails implements UserDetails, StagedUserDetails {
public void setAuthorities(Collection<Role> authorities) { this.authorities = authorities; }
public void setUsername(String username) { this.username = username; }
public String getUsername() { return username; }
public String getPassword() { return ""; }
public Collection<Role> getAuthorities() { return authorities; }
public boolean isAccountNonExpired() { return !expired; }
public boolean isAccountNonLocked() { return !expired; }
public boolean isCredentialsNonExpired() { return !expired; }
public boolean isEnabled() { return !expired; }
public DateTime getLastLogin() { return lastLogin; }
public void setLastLogin(DateTime lastLogin) { this.lastLogin = lastLogin; }
@Override public String getUsername() { return username; }
@Override public String getPassword() { return ""; }
@Override public Collection<Role> getAuthorities() { return authorities; }
@Override public boolean isAccountNonExpired() { return !expired; }
@Override public boolean isAccountNonLocked() { return !expired; }
@Override public boolean isCredentialsNonExpired() { return !expired; }
@Override public boolean isEnabled() { return !expired; }
@Override public String getNameId() { return username; }
@Override
public int getMaxAuthorityLevel() {
int level = 0;
if (getAuthorities() != null) {
......@@ -73,10 +78,8 @@ public class SimpleUserDetails implements UserDetails, StagedUserDetails {
return level;
}
@Override
public boolean isAuthorized(Role compRole) {
return getMaxAuthorityLevel() >= compRole.getLevel();
}
}
\ No newline at end of file
package eu.dariah.de.dariahsp.service;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import eu.dariah.de.dariahsp.model.User;
public abstract class BaseUserService implements UserService {
public static final String DEFAULT_LOCAL_DOMAIN = "LOCAL";
@Override
public final UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
return this.loadUserByUsername(this.getLocalDomain(), username);
}
@Override
public final void saveUser(User persistedUser) {
if (persistedUser!=null) {
if (persistedUser.getEndpointId()==null || persistedUser.getEndpointId().isEmpty()) {
persistedUser.setEndpointId(this.getLocalDomain());
persistedUser.setEndpointId(this.getLocalDomain());
}
}
this.innerSaveUser(persistedUser);
}
/**
* Getter for the localDomain field; defaults to DEFAULT_LOCAL_DOMAIN = "LOCAL"
* override if required
*
* @return local domain, default "LOCAL"
*/
protected String getLocalDomain() { return DEFAULT_LOCAL_DOMAIN; };
protected abstract void innerSaveUser(User persistedUser);
}
package eu.dariah.de.dariahsp.service;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import eu.dariah.de.dariahsp.model.User;
public interface UserService extends UserDetailsService {
public User loadUserByUsername(String domain, String username) throws UsernameNotFoundException;
public void saveUser(User persistedUser);
}
package eu.dariah.de.dariahsp.web;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.util.StringUtils;
import org.springframework.web.servlet.LocaleResolver;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
import org.springframework.web.servlet.support.RequestContextUtils;
import eu.dariah.de.dariahsp.web.AuthInfoHelper;
import eu.dariah.de.dariahsp.model.web.AuthPojo;;
public class AuthInfoHandlerInterceptor extends HandlerInterceptorAdapter {
private AuthInfoHelper authInfoHelper;
public AuthInfoHelper getAuthInfoHelper() { return authInfoHelper; }
public void setAuthInfoHelper(AuthInfoHelper authInfoHelper) { this.authInfoHelper = authInfoHelper; }
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
if (modelAndView==null) {
return;
}
AuthPojo auth = authInfoHelper.getAuth(request);
if (auth!=null && auth.isAuth()) {
modelAndView.addObject("_auth", auth);
setUserLocale(request, response, auth.getLanguage());
}
}
private void setUserLocale(final HttpServletRequest request, final HttpServletResponse response, String localeString) {
if (localeString != null && !localeString.isEmpty()) {
LocaleResolver localeResolver = RequestContextUtils.getLocaleResolver(request);
if (localeResolver == null) {
throw new IllegalStateException("No LocaleResolver found: not in a DispatcherServlet request?");
}
localeResolver.setLocale(request, response, StringUtils.parseLocaleString(localeString));
}
}
}
\ No newline at end of file
package eu.dariah.de.dariahsp.web.helper;
package eu.dariah.de.dariahsp.web;
import java.util.ArrayList;
import javax.servlet.http.HttpServletRequest;
......@@ -9,7 +9,7 @@ import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import eu.dariah.de.dariahsp.model.SimpleUserDetails;
import eu.dariah.de.dariahsp.model.UserImpl;
import eu.dariah.de.dariahsp.model.web.AuthPojo;
public class AuthInfoHelper {
......@@ -57,9 +57,9 @@ public class AuthInfoHelper {
pojo.getRoles().add(authority.getAuthority());
}
}
if (user instanceof SimpleUserDetails) {
pojo.setLevel(((SimpleUserDetails)user).getMaxAuthorityLevel());
pojo.setUserId(((SimpleUserDetails)user).getId());
if (user instanceof UserImpl) {
pojo.setLevel(((UserImpl)user).getMaxAuthorityLevel());
pojo.setUserId(((UserImpl)user).getId());
}
}
return pojo;
......
package eu.dariah.de.dariahsp.web;
import java.util.ArrayList;
import java.util.Collection;
import org.joda.time.DateTime;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import eu.dariah.de.dariahsp.model.Role;
import eu.dariah.de.dariahsp.model.RoleImpl;
import eu.dariah.de.dariahsp.model.User;
import eu.dariah.de.dariahsp.model.UserImpl;
import eu.dariah.de.dariahsp.service.BaseUserService;
import eu.dariah.de.dariahsp.service.UserService;
public class LocalAuthenticationProvider implements AuthenticationProvider {
private UserService userService;
private UserDetailsService localUserDb;
public UserService getUserService() { return userService; }
public void setUserService(UserService userService) { this.userService = userService; }
public UserDetailsService getLocalUserDb() { return localUserDb; }
public void setLocalUserDb(UserDetailsService localUserDb) { this.localUserDb = localUserDb; }
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
try {
UserDetails user = getLocalUserDb().loadUserByUsername(authentication.getName());
if (user.getPassword().equals(authentication.getCredentials())) {
UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken(user.getUsername(), user.getPassword().hashCode(), user.getAuthorities());
auth.setDetails(this.getUserDetails(user));
return auth;
} else {
throw new BadCredentialsException("Wrong password");
}
} catch (AuthenticationException e) {
throw new BadCredentialsException("Provided username and/or password wrong.");
}
}
@Override
public boolean supports(Class<?> authentication) {
return authentication.isAssignableFrom(UsernamePasswordAuthenticationToken.class);
}
private User getUserDetails(UserDetails user) {
User authorizedUser = null;
if (this.getUserService()!=null) {
authorizedUser = getUserService().loadUserByUsername(BaseUserService.DEFAULT_LOCAL_DOMAIN, user.getUsername());
}
if (authorizedUser==null) {
authorizedUser = new UserImpl();
authorizedUser.setEndpointId(BaseUserService.DEFAULT_LOCAL_DOMAIN);
authorizedUser.setEndpointName(BaseUserService.DEFAULT_LOCAL_DOMAIN);
authorizedUser.setHasAllAttributes(true);
authorizedUser.setUsername(user.getUsername());
}
Collection<Role> roles = new ArrayList<Role>();
for (GrantedAuthority r : user.getAuthorities()) {
roles.add(new RoleImpl(r.getAuthority()));
}
authorizedUser.setAuthorities(roles);
authorizedUser.setExpired(!(user.isAccountNonExpired() && user.isAccountNonLocked() && user.isCredentialsNonExpired() && user.isEnabled()));
authorizedUser.setLastLogin(DateTime.now());
if (this.getUserService()!=null) {
getUserService().saveUser(authorizedUser);
}
return authorizedUser;
}
}
<beans:beans xmlns:beans="http://www.springframework.org/schema/beans"
xmlns="http://www.springframework.org/schema/security"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<!-- USER CONFIGURATION: Configure local users below -->
<user-service id="localUserDb">
<user name="testadmin" password="nimda" authorities="ROLE_ADMINISTRATOR, ROLE_CONTRIBUTOR" />
<user name="testuser" password="sesu" authorities="" />
<user name="testcontributor" password="rotubirnoc" authorities="ROLE_CONTRIBUTOR" />
</user-service>
<!-- Without user detail persistence -->
<beans:bean id="localAuthenticationProvider" class="eu.dariah.de.dariahsp.web.LocalAuthenticationProvider">
<beans:property name="localUserDb" ref="localUserDb" />
</beans:bean>
<!-- With user detail persistence
<beans:bean id="localAuthenticationProvider" class="eu.dariah.de.dariahsp.web.LocalAuthenticationProvider">
<beans:property name="localUserDb" ref="localUserDb" />
<beans:property name="userService">
<beans:bean class="extension of eu.dariah.de.dariahsp.service.BaseUserService" />
</beans:property>
</beans:bean> -->
<http security="none" pattern="/resources/**"/>
<http disable-url-rewriting="true" auto-config="true" use-expressions="false" entry-point-ref="ajaxEntryPoint" access-decision-manager-ref="accessDecisionManager" >
<csrf disabled="true"/>
<intercept-url pattern="/test/jumboFluid" requires-channel="http" access="IS_AUTHENTICATED_FULLY" />
<form-login
authentication-success-handler-ref="simpleUrlAuthenticationSuccessHandler"
login-page="/login"
authentication-failure-url="/login?error"
username-parameter="username"
password-parameter="password"
/>
<logout invalidate-session="true" logout-url="/logout" logout-success-url="/" />
</http>
<beans:bean id="simpleUrlAuthenticationSuccessHandler" class="org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler">
<beans:property name="defaultTargetUrl" value="/"/>
<beans:property name="targetUrlParameter" value="redirectUrl"/>
</beans:bean>
<global-method-security pre-post-annotations="enabled" secured-annotations="enabled" />
<beans:bean id="ajaxEntryPoint" class="org.springframework.security.web.authentication.Http403ForbiddenEntryPoint">
</beans:bean>
<beans:bean id="authInfoHelper" class="eu.dariah.de.dariahsp.web.AuthInfoHelper" />
<authentication-manager alias="authenticationManager">
<authentication-provider ref="localAuthenticationProvider" />
</authentication-manager>
<beans:bean id="accessDecisionManager" class="org.springframework.security.access.vote.UnanimousBased">
<beans:constructor-arg name="decisionVoters">
<beans:list>
<beans:bean class="org.springframework.security.access.vote.AuthenticatedVoter" />
<beans:bean class="org.springframework.security.access.vote.RoleVoter" />
</beans:list>
</beans:constructor-arg>
<beans:property name="allowIfAllAbstainDecisions" value="false" />
</beans:bean>
</beans:beans>
\ No newline at end of file
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment