Add REST sample
Fixes gh-89
This commit is contained in:
@@ -4,6 +4,7 @@ commonsPoolVersion=2.2
|
||||
embeddedRedisVersion=0.2
|
||||
gebVersion=0.10.0
|
||||
groovyVersion=2.3.8
|
||||
jacksonVersion=2.4.4
|
||||
jedisVersion=2.4.1
|
||||
jstlVersion=1.2.1
|
||||
seleniumVersion=2.44.0
|
||||
|
||||
24
samples/rest/build.gradle
Normal file
24
samples/rest/build.gradle
Normal file
@@ -0,0 +1,24 @@
|
||||
apply from: JAVA_GRADLE
|
||||
apply from: TOMCAT_GRADLE
|
||||
|
||||
tasks.findByPath("artifactoryPublish")?.enabled = false
|
||||
sonarRunner {
|
||||
skipProject = true
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compile project(':spring-session-data-redis'),
|
||||
"org.springframework:spring-webmvc:$springVersion",
|
||||
"redis.embedded:embedded-redis:0.2",
|
||||
"org.springframework.security:spring-security-config:$springSecurityVersion",
|
||||
"org.springframework.security:spring-security-web:$springSecurityVersion",
|
||||
"com.fasterxml.jackson.core:jackson-databind:$jacksonVersion",
|
||||
jstlDependencies
|
||||
|
||||
providedCompile "javax.servlet:javax.servlet-api:$servletApiVersion"
|
||||
|
||||
testCompile 'junit:junit:4.11'
|
||||
|
||||
integrationTestCompile spockDependencies,
|
||||
'org.codehaus.groovy.modules.http-builder:http-builder:0.7'
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
package sample
|
||||
|
||||
import groovyx.net.http.HttpResponseException
|
||||
import groovyx.net.http.RESTClient
|
||||
import spock.lang.Shared
|
||||
import spock.lang.Specification
|
||||
import spock.lang.Stepwise
|
||||
|
||||
import javax.servlet.http.HttpServletResponse
|
||||
|
||||
/**
|
||||
* Ensures that Spring Security and Session are working
|
||||
*
|
||||
* @author Rob Winch
|
||||
*/
|
||||
@Stepwise
|
||||
class RestTests extends Specification {
|
||||
|
||||
@Shared
|
||||
RESTClient client = new RESTClient(System.properties.'geb.build.baseUrl')
|
||||
|
||||
@Shared
|
||||
String session
|
||||
|
||||
def 'Unauthenticated user sent to log in page'() {
|
||||
when: 'unauthenticated user request protected page'
|
||||
def resp = client.get path: '/', headers: ['Accept':'application/json']
|
||||
then: 'sent to the log in page'
|
||||
def e = thrown(HttpResponseException)
|
||||
e.response.status == HttpServletResponse.SC_UNAUTHORIZED
|
||||
}
|
||||
|
||||
def 'Authenticate with Basic Works'() {
|
||||
when: 'Authenticate with Basic'
|
||||
def username, response
|
||||
client.get(path: '/', headers: ['Authorization': 'Basic ' + 'user:password'.bytes.encodeBase64() ]) { resp, json ->
|
||||
response = resp
|
||||
username = json.username
|
||||
session = resp.headers.'x-auth-token'
|
||||
}
|
||||
then: 'Access the User information and obtain session via x-auth-token header'
|
||||
response.status == HttpServletResponse.SC_OK
|
||||
username == 'user'
|
||||
session
|
||||
}
|
||||
|
||||
def 'Authenticate with x-auth-token works'() {
|
||||
when: 'Authenticate with x-auth-token'
|
||||
def username, response
|
||||
client.get(path: '/', headers: ['x-auth-token': session ]) { resp, json ->
|
||||
response = resp
|
||||
username = json.username
|
||||
}
|
||||
then: 'Access the User information'
|
||||
response.status == HttpServletResponse.SC_OK
|
||||
username == 'user'
|
||||
}
|
||||
|
||||
def 'Logout'() {
|
||||
when: 'invalide session'
|
||||
def response
|
||||
client.get(path: '/logout', headers: ['x-auth-token': session ]) { resp, json ->
|
||||
response = resp
|
||||
session = resp.headers.'x-auth-token'
|
||||
}
|
||||
then: 'The session is deleted and an empty x-auth-token is returned'
|
||||
response.status == HttpServletResponse.SC_NO_CONTENT
|
||||
session == ''
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
package sample;
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.DisposableBean;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
import redis.clients.jedis.Protocol;
|
||||
import redis.embedded.RedisServer;
|
||||
|
||||
/**
|
||||
* Runs an embedded Redis instance. This is only necessary since we do not want
|
||||
* users to have to setup a Redis instance. In a production environment, this
|
||||
* would not be used since a Redis Server would be setup.
|
||||
*
|
||||
* @author Rob Winch
|
||||
*/
|
||||
@Configuration
|
||||
public class EmbeddedRedisConfiguration {
|
||||
|
||||
@Bean
|
||||
public static RedisServerBean redisServer() {
|
||||
return new RedisServerBean();
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements BeanDefinitionRegistryPostProcessor to ensure this Bean
|
||||
* is initialized before any other Beans. Specifically, we want to ensure
|
||||
* that the Redis Server is started before RedisHttpSessionConfiguration
|
||||
* attempts to enable Keyspace notifications.
|
||||
*/
|
||||
static class RedisServerBean implements InitializingBean, DisposableBean, BeanDefinitionRegistryPostProcessor {
|
||||
private RedisServer redisServer;
|
||||
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
redisServer = new RedisServer(Protocol.DEFAULT_PORT);
|
||||
redisServer.start();
|
||||
}
|
||||
|
||||
public void destroy() throws Exception {
|
||||
if(redisServer != null) {
|
||||
redisServer.stop();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {}
|
||||
|
||||
@Override
|
||||
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {}
|
||||
}
|
||||
}
|
||||
43
samples/rest/src/main/java/sample/HttpSessionConfig.java
Normal file
43
samples/rest/src/main/java/sample/HttpSessionConfig.java
Normal file
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
*
|
||||
* 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 sample;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
|
||||
import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession;
|
||||
import org.springframework.session.web.http.HeaderHttpSessionStrategy;
|
||||
import org.springframework.session.web.http.HttpSessionStrategy;
|
||||
|
||||
/**
|
||||
* @author Rob Winch
|
||||
*/
|
||||
@Configuration
|
||||
@Import(EmbeddedRedisConfiguration.class) // <1>
|
||||
@EnableRedisHttpSession // <2>
|
||||
public class HttpSessionConfig {
|
||||
|
||||
@Bean
|
||||
public JedisConnectionFactory connectionFactory() {
|
||||
return new JedisConnectionFactory(); // <3>
|
||||
}
|
||||
|
||||
@Bean
|
||||
public HttpSessionStrategy httpSessionStrategy() {
|
||||
return new HeaderHttpSessionStrategy(); // <4>
|
||||
}
|
||||
}
|
||||
25
samples/rest/src/main/java/sample/Initializer.java
Normal file
25
samples/rest/src/main/java/sample/Initializer.java
Normal file
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
*
|
||||
* 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 sample;
|
||||
|
||||
import org.springframework.session.web.context.AbstractHttpSessionApplicationInitializer;
|
||||
|
||||
/**
|
||||
* @author Rob Winch
|
||||
*/
|
||||
public class Initializer extends AbstractHttpSessionApplicationInitializer {
|
||||
|
||||
}
|
||||
46
samples/rest/src/main/java/sample/SecurityConfig.java
Normal file
46
samples/rest/src/main/java/sample/SecurityConfig.java
Normal file
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
*
|
||||
* 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 sample;
|
||||
|
||||
/**
|
||||
* @author Rob Winch
|
||||
*/
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
|
||||
|
||||
@EnableWebSecurity
|
||||
public class SecurityConfig extends WebSecurityConfigurerAdapter {
|
||||
|
||||
@Override
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
http
|
||||
.authorizeRequests()
|
||||
.anyRequest().authenticated()
|
||||
.and()
|
||||
.httpBasic();
|
||||
}
|
||||
|
||||
@Autowired
|
||||
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
|
||||
auth
|
||||
.inMemoryAuthentication()
|
||||
.withUser("user").password("password").roles("USER");
|
||||
}
|
||||
}
|
||||
26
samples/rest/src/main/java/sample/SecurityInitializer.java
Normal file
26
samples/rest/src/main/java/sample/SecurityInitializer.java
Normal file
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
*
|
||||
* 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 sample;
|
||||
|
||||
import org.springframework.security.web.context.AbstractSecurityWebApplicationInitializer;
|
||||
|
||||
/**
|
||||
* @author Rob Winch
|
||||
*/
|
||||
public class SecurityInitializer extends
|
||||
AbstractSecurityWebApplicationInitializer {
|
||||
|
||||
}
|
||||
29
samples/rest/src/main/java/sample/mvc/MvcConfig.java
Normal file
29
samples/rest/src/main/java/sample/mvc/MvcConfig.java
Normal file
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
*
|
||||
* 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 sample.mvc;
|
||||
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
|
||||
|
||||
/**
|
||||
* @author Rob Winch
|
||||
*/
|
||||
@Configuration
|
||||
@EnableWebMvc
|
||||
@ComponentScan
|
||||
public class MvcConfig {
|
||||
}
|
||||
40
samples/rest/src/main/java/sample/mvc/MvcInializer.java
Normal file
40
samples/rest/src/main/java/sample/mvc/MvcInializer.java
Normal file
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
*
|
||||
* 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 sample.mvc;
|
||||
|
||||
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
|
||||
import sample.HttpSessionConfig;
|
||||
import sample.SecurityConfig;
|
||||
|
||||
/**
|
||||
* @author Rob Winch
|
||||
*/
|
||||
public class MvcInializer extends AbstractAnnotationConfigDispatcherServletInitializer {
|
||||
@Override
|
||||
protected Class<?>[] getRootConfigClasses() {
|
||||
return new Class[] {SecurityConfig.class, HttpSessionConfig.class};
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Class<?>[] getServletConfigClasses() {
|
||||
return new Class[] { MvcConfig.class };
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String[] getServletMappings() {
|
||||
return new String[] { "/" };
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
*
|
||||
* 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 sample.mvc;
|
||||
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
import org.springframework.web.bind.annotation.ResponseStatus;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import javax.servlet.http.HttpSession;
|
||||
import java.security.Principal;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author Rob Winch
|
||||
*/
|
||||
@RestController
|
||||
public class RestDemoController {
|
||||
|
||||
@RequestMapping(value="/",produces = "application/json")
|
||||
public Map<String,String> helloUser(Principal principal) {
|
||||
HashMap<String,String> result = new HashMap<String,String>();
|
||||
result.put("username", principal.getName());
|
||||
return result;
|
||||
}
|
||||
|
||||
@RequestMapping("/logout")
|
||||
@ResponseStatus(HttpStatus.NO_CONTENT)
|
||||
public void logout(HttpSession session) {
|
||||
session.invalidate();
|
||||
}
|
||||
}
|
||||
0
samples/rest/src/main/webapp/META-INF/MANIFEST.MF
Normal file
0
samples/rest/src/main/webapp/META-INF/MANIFEST.MF
Normal file
@@ -5,6 +5,7 @@ include 'docs'
|
||||
include 'samples:boot'
|
||||
include 'samples:hazelcast'
|
||||
include 'samples:httpsession'
|
||||
include 'samples:rest'
|
||||
include 'samples:security'
|
||||
include 'samples:users'
|
||||
include 'samples:websocket'
|
||||
|
||||
Reference in New Issue
Block a user