Example of custom implementation of UserDetails - spring

I am looking for an example of making a custom UserDetails object in Spring Security 3.
And I was hoping if anyone can help, thanks.

Here's what I've used:
public class CustomUserDetails implements UserDetails {
private User user;
public CustomUserDetails(final User _user) {
this.user = _user;
}
public CustomUserDetails() {
}
#Override
public Collection<GrantedAuthority> getAuthorities() {
final Set<GrantedAuthority> _grntdAuths = new HashSet<GrantedAuthority>();
List<UserRole> _roles = null;
if (user!=null) {
_roles = user.getRoles();
}
if (_roles!=null) {
for (UserRole _role : _roles) {
_grntdAuths.add(new GrantedAuthorityImpl(_role.getRole()));
}
}
return _grntdAuths;
}
#Override
public String getPassword() {
return user.getPassword();
}
#Override
public String getUsername() {
if (this.user == null) {
return null;
}
return this.user.getUser_name();
}
#Override
public boolean isAccountNonExpired() {
return this.user.isAccountNonExpired();
}
#Override
public boolean isAccountNonLocked() {
return this.user.isAccountNonLocked();
}
#Override
public boolean isCredentialsNonExpired() {
return this.user.isCredentialsNonExpired();
}
#Override
public boolean isEnabled() {
return this.user.isEnabled();
}
public User getUser() {
return user;
}
#Override
public String toString() {
return "CustomUserDetails [user=" + user + "]";
}
}

Related

Get additional security user fields without calling findByUsername

I'm calling the findUserByUsername() method to get the name field in the User entity and I'm wondering if there's any better to do it without having to execute an addional query
AuthenticationController.java
#PostMapping("/login")
public ResponseEntity<AuthenticationResponse> login (#RequestBody AuthenticationRequest userLogin) {
try {
Authentication authentication = authenticationManager
.authenticate(new UsernamePasswordAuthenticationToken(userLogin.username(), userLogin.password()));
String token = tokenService.generateToken(authentication);
Optional<User> user = userRepository.findByUsername(authentication.getName());
AuthenticationResponse response = new AuthenticationResponse(user.get().getName(), token);
return ResponseEntity.ok().body(response);
} catch (BadCredentialsException e) {
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build();
}
}
SecurityUser.java
public class SecurityUser implements UserDetails {
private final User user;
public SecurityUser (User user) {
this.user = user;
}
#Override
public String getUsername() {
return user.getUsername();
}
#Override
public String getPassword() {
return user.getPassword();
}
#Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return user
.getRoles()
.stream()
.map(role -> new SimpleGrantedAuthority(role.getName()))
.collect(Collectors.toSet());
}
#Override
public boolean isAccountNonExpired() {
return true;
}
#Override
public boolean isAccountNonLocked() {
return true;
}
#Override
public boolean isCredentialsNonExpired() {
return true;
}
#Override
public boolean isEnabled() {
return true;
}
#Override
public String toString() {
return "SecurityUser{" +
"user=" + user +
'}';
}
}
Depending on how your security configuration is set up, you can use authentication.getName(), as it usually maps to the username field. This would be the case with formLogin() for example, which uses the DaoAuthenticationProvider under the covers.

How to resolve getPrincipal() method error

While accessing the services using JWT token i was trying to print auth.getPrincipal() method it returning packageName.model.CustomUserDetails#3f97b72b instead of the UserDto details.
CustomUserDetails
public class CustomUserDetails implements UserDetails {
private static final long serialVersionUID = 8632209412694363798L;
private UsersDto userDto;
private UserEntity user;
public CustomUserDetails(UsersDto userDto) {
super();
this.userDto = userDto;
}
public UsersDto getUserDto() {
return userDto;
}
public void setUserDto(UsersDto userDto) {
this.userDto = userDto;
}
public CustomUserDetails(UserEntity user) {
this.user = user;
}
#Override
public Collection<? extends GrantedAuthority> getAuthorities() {
// List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
// UserRole role = userDto.getRole();
// authorities.add(new SimpleGrantedAuthority(role.name()));
// return authorities;
return null;
}
#Override
public String getPassword() {
return user.getPassword();
}
#Override
public String getUsername() {
return user.getEmail();
}
#Override
public boolean isAccountNonExpired() {
return true;
}
#Override
public boolean isAccountNonLocked() {
return true;
}
#Override
public boolean isCredentialsNonExpired() {
return true;
}
#Override
public boolean isEnabled() {
return true;
}
}
UsersDto
#Data
#NoArgsConstructor
#AllArgsConstructor
public class UsersDto extends User {
private Integer userId;
public UserEntity convertToUserEntity() throws NoSuchAlgorithmException {
UserEntity user=new UserEntity();
user.setUserId(this.userId);
user.setName(this.getName());
user.setEmail(this.getEmail());
user.setDateAdded(this.getDateAdded());
user.setDateModified(this.getDateModified());
user.setPassword(this.getPassword());
user.setPassword(this.getPassword());
return user;
}
}
UserController
#GetMapping("/getUser/{userId}")
public ResponseEntity<SuccessResponse> getuser(#PathVariable Integer userId,Authentication auth) throws Exception{
System.out.println(auth);
System.out.println(auth.getPrincipal());
UsersDto userFromAuth = ((CustomUserDetails) auth.getPrincipal()).getUserDto();
return ResponseEntity
.ok(new SuccessResponse(HttpStatus.OK.value(), SuccessMessage.SUCCESS,
userService.getUserById(userId)));
}
error
**packagename.CustomUserDetails#3f97b72b**
Instead of class details I want userdetails but it returning className with uniformed number so when i store this data into a variable it always stores NULL values.

WithMockUser not working, but SecurityContext.getContext().setAuthentification does

I try to mock login with #WithMockUserbut it is not working.
#SpringBootTest
class RoleTest {
#Autowired
private UserService userService;
#Autowired
private RoleService roleService;
private User user;
#BeforeEach
void setUp() {
AuthentificationService.AuthentificationMock.loginAsAdminOnly();
user = new User("maier", "password", "Hansi", "Meier", "hanmai#maier.de", "+4953353535353", roleService.getByName(Role.ROLE_ADMIN).orElse(null));
assertNotNull(user.getRoles());
userService.save(user);
AuthentificationService.AuthentificationMock.logout();
}
#AfterEach
void tearDown() {
AuthentificationService.AuthentificationMock.loginAsAdminOnly();
userService.delete(user);
AuthentificationService.AuthentificationMock.logout();
}
#Test
#WithMockUser(Role.ADMIN)
void testRoleHierarchy() {
boolean succeeded = true;
//WHEN
try {
final Optional<User> byUsername = userService.getByUsernameResolved(user.getUsername());
} catch (Exception e) {
succeeded = false;
}
//THEN
assertTrue(succeeded, "ADMIN has no USER Privileges, check RoleHierarchy");
}
}
If I run test authentication there is an AuthenticationCredentialsNotFoundException and so test fails.
That is the Service which the access is limited:
#Service
#Slf4j
#Transactional
#NoArgsConstructor
public class UserService implements JpaServiceContract<User>, UserDetailsService {
private UserRepository userRepository;
private AuthenticationManager authenticationManager;
private PasswordEncoder passwordEncoder;
#Autowired
public UserService(PasswordEncoder passwordEncoder, AuthenticationManager authenticationManager, UserRepository userRepository) {
this.userRepository = userRepository;
this.authenticationManager = authenticationManager;
this.passwordEncoder = passwordEncoder;
}
#Override
public UserDetails loadUserByUsername(#NotNull String username) {
final String callerName = SharedSecrets.getJavaLangAccess().getStackTraceElement(new Throwable(), 12).getClassName();
if (!callerName.equals("app.config.security.TokenAuthenticationFilter")) {
throw new MethodAccessException();
}
SecurityContextHolder.getContext().setAuthentication(new PreAuthenticatedAuthenticationToken(null, null, Collections.singletonList(new Role(Role.ADMIN))));
Optional<User> user = getByUsernameResolved(username);
SecurityContextHolder.clearContext();
final User user1 = user.orElse(null);
assert user1 != null;
return user1;
}
/**
* This Method is same as {#link #getByUsername(String)} but it resolves all Lazy loaded Properties,
* which could not be resolved outside of the current Transaction anymore
*
* #param username Of the {#link app.model.authentification.User} which should be found
* #return The {#link app.model.authentification.User} found as an {#link java.util.Optional}
*/
#RolesAllowed(value = Role.ROLE_USER)
public Optional<User> getByUsernameResolved(#NotNull String username) {
final Optional<User> userUnresolved = getByUsername(username);
userUnresolved.ifPresent(user -> Hibernate.initialize(user.getRoles()));
return userUnresolved;
}
#RolesAllowed(value = Role.ROLE_USER)
public Optional<User> getByUsername(#NotNull String username) {
if (!existsByUsername(username)) {
throw new RessourceNotFoundException("User not found");
}
return userRepository.findByUsername(username);
}
#Override
#RolesAllowed(Role.ROLE_USER)
public Optional<User> getById(#NotNull Long id) {
return userRepository.findById(id);
}
#Override
#RolesAllowed(Role.ROLE_USER)
public Optional<User> getByIdResolved(#NotNull Long id) {
final Optional<User> byId = getById(id);
if (byId.isPresent()) {
Hibernate.initialize(byId.get().getRoles());
return byId;
} else {
return Optional.empty();
}
}
#RolesAllowed(value = Role.ROLE_ADMIN)
#Override
public Set<User> getAll() {
return (Set<User>) userRepository.findAll();
}
#RolesAllowed(value = Role.ROLE_ADMIN)
#Override
public Set<User> getAllResolved() {
final Set<User> all = getAll();
Hibernate.initialize(all);
return all;
}
public User changePassword(#NotNull String oldPassword, #NotNull String newPassword) {
User user = getLoggedInUser();
user.setPassword(passwordEncoder.encode(newPassword));
return userRepository.save(user);
}
#Override
#RolesAllowed(value = Role.ROLE_USER)
public boolean existsById(#NotNull Long id) {
return userRepository.existsById(id);
}
#RolesAllowed(value = Role.ROLE_USER)
public boolean existsByUsername(#NotNull String username) {
return userRepository.existsByUsername(username);
}
#Override
#RolesAllowed(value = Role.ROLE_ADMIN)
public User save(#NotNull User user) throws RessourceAlreadyExistsException, InvalidParameterException {
if (UserValidator.isFullValid(user))
if (!userRepository.existsByUsername(user.getUsername())) {
user.setPassword(passwordEncoder.encode(user.getPassword()));
return userRepository.save(user);
} else {
throw new RessourceAlreadyExistsException(user.getUsername());
}
throw new InvalidParameterException(new String[]{"User"});
}
#Override
#RolesAllowed(Role.ROLE_USER)
public User update(#NotNull User user) throws InvalidParameterException {
if (UserValidator.isFullValid(user) && userRepository.existsByUsername(user.getUsername())) {
user.setPassword(passwordEncoder.encode(user.getPassword()));
return userRepository.save(user);
}
throw new InvalidParameterException(new String[]{"User"});
}
#Override
#RolesAllowed(value = Role.ROLE_ADMIN)
public void delete(#NotNull User user) throws IllegalArgumentException {
userRepository.delete(user);
}
#RolesAllowed(value = Role.ROLE_ADMIN)
public void delete(#NotNull String username) {
userRepository.deleteByUsername(username);
}
#RolesAllowed(value = Role.ROLE_USER)
private User getLoggedInUser() throws InvalidStateException {
Authentication currentUser = SecurityContextHolder.getContext().getAuthentication();
String username = currentUser.getName();
final Optional<User> userValue = getByUsername(username);
if (userValue.isPresent())
return userValue.get();
throw new InvalidStateException("User " + username + " not found");
}
}
If you like to I could provide more Information of Configuration but at the Moment I don't know if this is necessary. But if you believe it is I will.

What is the best way to use #ConfigurationProperties with Builders?

I have searched and can't find any examples that would show me a better way to do this, but in the Spring/Spring Boot code, there are generic builders but the builder itself seems to apply the properties programmatically. Here is some code trying to configure 2 Oracle Connection Pool Data Sources:
import oracle.ucp.jdbc.PoolDataSourceFactory;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import javax.sql.DataSource;
import java.sql.SQLException;
#Configuration
#EnableConfigurationProperties
#ConditionalOnClass(PoolDataSourceFactory.class)
public class PersistenceAutoConfiguration {
#Bean (name = "readWriteDataSource")
public DataSource getReadWriteDataSource() throws SQLException {
OracleUcpDataSourceProperties rwProperties = getReadWriteProperties();
return OracleUcpDataSourceBuilder.create()
.connectionFactoryClassName(rwProperties.getConnectionFactoryClassName())
.url(rwProperties.getUrl())
.user(rwProperties.getUser())
.password(rwProperties.getPassword())
.initialPoolSize(rwProperties.getInitialPoolSize())
.minPoolSize(rwProperties.getMinPoolSize())
.maxPoolSize(rwProperties.getMaxPoolSize())
.connectionWaitTimeout(rwProperties.getConnectionWaitTimeout())
.inactiveConnectionTimeout(rwProperties.getInactiveConnectionTimeout())
.maxIdleTime(rwProperties.getMaxIdleTime())
.build();
}
#Bean (name = "readOnlyDataSource")
public DataSource getReadOnlyDataSource() throws SQLException {
OracleUcpDataSourceProperties roProperties = getReadOnlyProperties();
return OracleUcpDataSourceBuilder.create()
.connectionFactoryClassName(roProperties.getConnectionFactoryClassName())
.url(roProperties.getUrl())
.user(roProperties.getUser())
.password(roProperties.getPassword())
.initialPoolSize(roProperties.getInitialPoolSize())
.minPoolSize(roProperties.getMinPoolSize())
.maxPoolSize(roProperties.getMaxPoolSize())
.connectionWaitTimeout(roProperties.getConnectionWaitTimeout())
.inactiveConnectionTimeout(roProperties.getInactiveConnectionTimeout())
.maxIdleTime(roProperties.getMaxIdleTime())
.build();
}
#ConfigurationProperties(prefix = "datasource.readwrite")
#Bean(name = "readWriteProperties")
protected OracleUcpDataSourceProperties getReadWriteProperties() {
return new OracleUcpDataSourceProperties();
}
#ConfigurationProperties(prefix = "datasource.readonly")
#Bean(name = "readOnlyProperties")
protected OracleUcpDataSourceProperties getReadOnlyProperties() {
return new OracleUcpDataSourceProperties();
}
}
and
public class OracleUcpDataSourceProperties {
private String connectionFactoryClassName;
private String url;
private String user;
private String password;
private int initialPoolSize;
private int minPoolSize;
private int maxPoolSize;
private int connectionWaitTimeout;
private int inactiveConnectionTimeout;
private int maxIdleTime;
private Boolean validateConnectionOnBorrow;
public String getConnectionFactoryClassName() {
return connectionFactoryClassName;
}
public void setConnectionFactoryClassName(String connectionFactoryClassName) {
this.connectionFactoryClassName = connectionFactoryClassName;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getUser() {
return user;
}
public void setUser(String user) {
this.user = user;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public int getInitialPoolSize() {
return initialPoolSize;
}
public void setInitialPoolSize(int initialPoolSize) {
this.initialPoolSize = initialPoolSize;
}
public int getMinPoolSize() {
return minPoolSize;
}
public void setMinPoolSize(int minPoolSize) {
this.minPoolSize = minPoolSize;
}
public int getMaxPoolSize() {
return maxPoolSize;
}
public void setMaxPoolSize(int maxPoolSize) {
this.maxPoolSize = maxPoolSize;
}
public int getConnectionWaitTimeout() {
return connectionWaitTimeout;
}
public void setConnectionWaitTimeout(int connectionWaitTimeout) {
this.connectionWaitTimeout = connectionWaitTimeout;
}
public int getInactiveConnectionTimeout() {
return inactiveConnectionTimeout;
}
public void setInactiveConnectionTimeout(int inactiveConnectionTimeout) {
this.inactiveConnectionTimeout = inactiveConnectionTimeout;
}
public int getMaxIdleTime() {
return maxIdleTime;
}
public void setMaxIdleTime(int maxIdleTime) {
this.maxIdleTime = maxIdleTime;
}
public Boolean getValidateConnectionOnBorrow() {
return validateConnectionOnBorrow;
}
public void setValidateConnectionOnBorrow(Boolean validateConnectionOnBorrow) {
this.validateConnectionOnBorrow = validateConnectionOnBorrow;
}
}
and
import oracle.ucp.jdbc.PoolDataSource;
import oracle.ucp.jdbc.PoolDataSourceFactory;
import java.sql.SQLException;
public class OracleUcpDataSourceBuilder {
private PoolDataSource pds;
/**
* This will grab the pool factory and initialize it.
*/
public OracleUcpDataSourceBuilder() throws SQLException {
pds = PoolDataSourceFactory.getPoolDataSource();
}
public static OracleUcpDataSourceBuilder create() throws SQLException {
return new OracleUcpDataSourceBuilder();
}
public OracleUcpDataSourceBuilder connectionFactoryClassName(String connectionFactoryClassName) throws SQLException {
pds.setConnectionFactoryClassName(connectionFactoryClassName);
return this;
}
public OracleUcpDataSourceBuilder url(String url) throws SQLException {
pds.setURL(url);
return this;
}
public OracleUcpDataSourceBuilder user(String user) throws SQLException {
pds.setUser(user);
return this;
}
public OracleUcpDataSourceBuilder password(String password) throws SQLException {
pds.setPassword(password);
return this;
}
public OracleUcpDataSourceBuilder initialPoolSize(int initialPoolSize) throws SQLException {
pds.setInitialPoolSize(initialPoolSize);
return this;
}
public OracleUcpDataSourceBuilder minPoolSize(int minPoolSize) throws SQLException {
pds.setMinPoolSize(minPoolSize);
return this;
}
public OracleUcpDataSourceBuilder maxPoolSize(int maxPoolSize) throws SQLException {
pds.setMaxPoolSize(maxPoolSize);
return this;
}
public OracleUcpDataSourceBuilder connectionWaitTimeout(int connectionWaitTimeout) throws SQLException {
pds.setConnectionWaitTimeout(connectionWaitTimeout);
return this;
}
public OracleUcpDataSourceBuilder inactiveConnectionTimeout(int inactiveConnectionTime) throws SQLException {
pds.setInactiveConnectionTimeout(inactiveConnectionTime);
return this;
}
public OracleUcpDataSourceBuilder maxIdleTime(int maxIdleTime) throws SQLException {
pds.setMaxIdleTime(maxIdleTime);
return this;
}
public PoolDataSource build() {
return pds;
}
}
Preferably, I would like to be able to apply the properties directly to the builder in one place. is this possible? what changes would I have to make?
Thanks...
Here is your builder, sir
public class OracleUcpDataSourceBuilder {
private Map<String, String> properties = new HashMap<String, String>();
private static final String[] REQ_PROPERTIES = new String[] {"username", "password", "URL"};
public static OracleUcpDataSourceBuilder create() {
return new OracleUcpDataSourceBuilder();
}
public DataSource build() {
for (String prop : REQ_PROPERTIES) {
Assert.notNull(properties.get(prop), "Property is required:" + prop);
}
PoolDataSource result = PoolDataSourceFactory.getPoolDataSource();
bind(result);
return result;
}
private void bind(DataSource result) {
MutablePropertyValues properties = new MutablePropertyValues(this.properties);
new RelaxedDataBinder(result).bind(properties);
}
public OracleUcpDataSourceBuilder URL(String url) {
this.properties.put("URL", url);
return this;
}
public OracleUcpDataSourceBuilder username(String username) {
this.properties.put("username", username);
return this;
}
public OracleUcpDataSourceBuilder password(String password) {
this.properties.put("password", password);
return this;
}
}
Just define a bean like this:
#Bean (name = "readOnlyDataSource")
#ConfigurationProperties(prefix = "datasource.readonly")
public DataSource getReadOnlyDataSource() {
return OracleUcpDataSourceBuilder.create().build();
}
Just make sure that the property names are correct. Spring will take care of the rest.
Note: I use DataSourceBuilder or Spring as a reference.. You can check it's source code also.
Edit: Added some methods to make sure some properties are configured. But this way, you need to set those properties manually to make sure that they're available.

window scope in spring?

i was wondering about the spring scope equivalent to window scope ?
according to the documentation here
http://static.springsource.org/spring/docs/3.0.0.M3/spring-framework-reference/html/ch04s04.html
i couldn't find any, so if there's a custom scope equivalent, can anyone please tell me, thanks.
EDIT: example of window scope in JSF
http://icefaces-showcase.icesoft.org/showcase.jsf?grp=compatMenu&exp=popup
One possible approach is having a session scoped bean that holds all the window sessions, and a window custom scope that access to the corresponding bean through that session scoped bean.
The required classes are:
Window Session
public class WindowSession {
private Map<String, Map<String,Object>> scopeMap = new HashMap<String, Map<String,Object>>();
private Map<String, Boolean> validSessions = new HashMap<String, Boolean>();
public WindowSession() {
super();
}
public Map<String, Map<String, Object>> getScopeMap() {
return scopeMap;
}
public void setScopeMap(Map<String, Map<String, Object>> scopeMap) {
this.scopeMap = scopeMap;
}
public Map<String, Boolean> getValidSessions() {
return validSessions;
}
public void setValidSessions(Map<String, Boolean> validSessions) {
this.validSessions = validSessions;
}
}
WindowIdContext
#Service
#Scope(value="request", proxyMode=ScopedProxyMode.TARGET_CLASS)
public class WindowIdContext {
public static final String DEFAULT_SESSION_ID = "";
private String id = DEFAULT_SESSION_ID;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getQueryParamWithSessionId() {
if (DEFAULT_SESSION_ID.equals(id)) {
return "";
}
return "?" + WindowScope.WINDOW_ID_PARAM + "=" + id;
}
}
WindowSessionContext
#Service
#Scope(value="session", proxyMode=ScopedProxyMode.TARGET_CLASS)
public class WindowSessionContext {
private static SecureRandom random = new SecureRandom();
private WindowSession windowSession = new WindowSession();
#Autowired
private WindowIdContext windowIdContext;
public WindowSessionContext() {
windowSession.getValidSessions().put(WindowIdContext.DEFAULT_SESSION_ID, false);
}
public Object getObject(String name, ObjectFactory<?> objectFactory) {
String sessionId = windowIdContext.getId();
synchronized(this) {
if (!windowSession.getValidSessions().containsKey(sessionId)) {
windowSession.getValidSessions().put(sessionId, false);
}
Map<String,Object> sessionMap = windowSession.getScopeMap().get(sessionId);
if (sessionMap == null) {
sessionMap = new HashMap<String,Object>();
windowSession.getScopeMap().put(sessionId, sessionMap);
}
Object object = sessionMap.get(name);
if (object == null) {
object = objectFactory.getObject();
sessionMap.put(name, object);
}
return object;
}
}
public Object removeObject(String name) {
String sessionId = windowIdContext.getId();
synchronized(this) {
Map<String,Object> sessionMap = windowSession.getScopeMap().get(sessionId);
if (sessionMap == null) {
return null;
}
Object object = sessionMap.remove(name);
return object;
}
}
public String addSession() {
synchronized(this) {
String sessionId;
do {
sessionId = new BigInteger(130, random).toString(32);
} while (windowSession.getValidSessions().containsKey(sessionId));
windowSession.getValidSessions().put(sessionId, false);
return sessionId;
}
}
public void removeSession() {
String sessionId = windowIdContext.getId();
synchronized(this) {
windowSession.getScopeMap().remove(sessionId);
windowSession.getValidSessions().remove(sessionId);
}
}
public boolean isSessionValid(String sessionId) {
Boolean inUse = windowSession.getValidSessions().get(sessionId);
return inUse != null;
}
public boolean isSessionInUse(String sessionId) {
Boolean inUse = windowSession.getValidSessions().get(sessionId);
return inUse == true;
}
public synchronized boolean invalidateSession(String sessionId) {
Boolean valid = windowSession.getValidSessions().get(sessionId);
if (valid == null) {
return false;
}
if (sessionId.equals(WindowIdContext.DEFAULT_SESSION_ID)) {
windowSession.getValidSessions().put(sessionId, false);
} else {
windowSession.getValidSessions().remove(sessionId);
}
windowSession.getScopeMap().remove(sessionId);
for (Entry<String,Boolean> validSession : windowSession.getValidSessions().entrySet()) {
if (validSession.getValue() == true) {
return false;
}
}
return true;
}
public synchronized void setSessionInUse(String sessionId) {
windowSession.getValidSessions().put(sessionId, true);
}
public int getCount() {
return windowSession.getValidSessions().size();
}
}
WindowScope
public class WindowScope implements Scope {
private final int scope;
private static final int WINDOW_SCOPE = 40;
public static final String NAME = "window";
public static final String WINDOW_ID_PARAM = "windowid";
private ServletContext servletContext = null;
public WindowScope(ServletContext sc) {
servletContext = sc;
this.scope = WINDOW_SCOPE;
}
#Override
public Object get(String name, ObjectFactory<?> objectFactory) {
ApplicationContext applicationContext = WebApplicationContextUtils.getWebApplicationContext(servletContext);
WindowSessionContext windowSessionContext = applicationContext.getBean(WindowSessionContext.class);
return windowSessionContext.getObject(name, objectFactory);
}
#Override
public Object remove(String name) {
ApplicationContext applicationContext = WebApplicationContextUtils.getWebApplicationContext(servletContext);
WindowSessionContext windowSessionContext = applicationContext.getBean(WindowSessionContext.class);
return windowSessionContext.removeObject(name);
}
#Override
public String getConversationId() {
return RequestContextHolder.currentRequestAttributes().getSessionId();
}
#Override
public void registerDestructionCallback(String arg0, Runnable arg1) {
}
#Override
public Object resolveContextualObject(String key) {
return null;
}
protected int getScope() {
return this.scope;
}
}
WindowScopeFilter
#Component("windowScopeFilter")
public class WindowScopeFilter implements Filter {
#Autowired
private WindowSessionContext windowSessionContext;
#Autowired
private WindowIdContext windowIdContext;
public void destroy() {
}
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest httpRequest = (HttpServletRequest)request;
HttpServletResponse httpResponse = (HttpServletResponse)response;
String sessionId = httpRequest.getParameter(WindowScope.WINDOW_ID_PARAM);
if (sessionId != null) {
if (windowSessionContext.isSessionValid(sessionId)) {
windowIdContext.setId(sessionId);
} else {
httpResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED);
}
} else {
windowSessionContext.setSessionInUse(WindowIdContext.DEFAULT_SESSION_ID);
}
chain.doFilter(request, response);
}
public void init(FilterConfig config) throws ServletException {
}
}
WindowScopeListener
#Component
public class WindowScopeListener implements ApplicationListener<ContextRefreshedEvent> {
#Override
public void onApplicationEvent(ContextRefreshedEvent event) {
WebApplicationContext applicationContext = (WebApplicationContext)event.getApplicationContext();
Scope windowScope = new WindowScope(applicationContext.getServletContext());
ConfigurableBeanFactory beanFactory = (ConfigurableBeanFactory)applicationContext.getAutowireCapableBeanFactory();
beanFactory.registerScope("window", windowScope);
}
}
Source with complete source code: http://notwithoutmycode.com/post/window/scope/in/spring

Resources