Permalink
Browse files

SEC-2092: Add servlet api example

  • Loading branch information...
1 parent 9c45632 commit 22e333b9c6e56d7806342fcda9154f9378d1d375 @rwinch rwinch committed Dec 11, 2012
@@ -0,0 +1,34 @@
+// Servlet API integration sample build file
+
+apply plugin: 'war'
+
+def excludeModules = ['spring-security-acl', 'jsr250-api', 'ehcache', 'spring-jdbc', 'spring-tx']
+
+configurations {
+ excludeModules.each {name ->
+ runtime.exclude module: name
+ }
+
+ runtime.exclude group: 'org.aspectj'
+}
+
+dependencies {
+ providedCompile "org.apache.tomcat:tomcat-servlet-api:$servletApiVersion"
+
+ compile project(':spring-security-core'),
+ project(':spring-security-web'),
+ "javax.servlet:jstl:$jstlVersion",
+ "org.springframework:spring-beans:$springVersion",
+ "org.springframework:spring-context:$springVersion",
+ "org.springframework:spring-web:$springVersion",
+ "org.springframework:spring-webmvc:$springVersion"
+
+ runtime project(':spring-security-config'),
+ project(':spring-security-taglibs'),
+ "org.springframework:spring-context-support:$springVersion",
+ "javax.servlet:jstl:$jstlVersion",
+ "org.slf4j:jcl-over-slf4j:$slf4jVersion",
+ "ch.qos.logback:logback-classic:$logbackVersion"
+}
+
+eclipse.wtp.component.contextPath = "servletapi"
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2002-2012 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 org.springframework.security.samples.servletapi.mvc;
+
+/**
+ *
+ * @author Rob Winch
+ *
+ */
+public class LoginForm {
+ private String username;
+ private String password;
+
+ public String getUsername() {
+ return username;
+ }
+ public void setUsername(String username) {
+ this.username = username;
+ }
+ public String getPassword() {
+ return password;
+ }
+ public void setPassword(String password) {
+ this.password = password;
+ }
+}
@@ -0,0 +1,192 @@
+/*
+ * Copyright 2002-2012 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 org.springframework.security.samples.servletapi.mvc;
+
+import java.io.IOException;
+import java.security.Principal;
+
+import javax.naming.AuthenticationException;
+import javax.servlet.AsyncContext;
+import javax.servlet.Servlet;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.context.SecurityContext;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.security.web.access.ExceptionTranslationFilter;
+import org.springframework.stereotype.Controller;
+import org.springframework.validation.BindingResult;
+import org.springframework.web.bind.annotation.ModelAttribute;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.servlet.mvc.support.RedirectAttributes;
+
+/**
+ * A Spring MVC Controller that demonstrates Spring Security's integration with the standard Servlet API's. Specifically
+ * it demonstrates the following:
+ * <ul>
+ * <li>{@link #authenticate(HttpServletRequest, HttpServletResponse)} - Integration with
+ * {@link HttpServletRequest#authenticate(HttpServletResponse)}</li>
+ * <li>{@link #login(HttpServletRequest, HttpServletResponse, LoginForm, BindingResult)} - Integration with
+ * {@link HttpServletRequest#login(String, String)}</li>
+ * <li>{@link #logout(HttpServletRequest, HttpServletResponse)} - Integration with {@link HttpServletRequest#logout()}</li>
+ * <li>{@link #remoteUser(HttpServletRequest)} - Integration with {@link HttpServletRequest#getRemoteUser()}</li>
+ * <li>{@link #userPrincipal(HttpServletRequest)} - Integration with {@link HttpServletRequest#getUserPrincipal()}</li>
+ * <li>{@link #authentication(Authentication)} - Spring MVC's ability to resolve the {@link Authentication} since it is
+ * found on {@link HttpServletRequest#getUserPrincipal()}</li>
+ * </ul>
+ *
+ * @author Rob Winch
+ *
+ */
+@Controller
+public class ServletApiController {
+ /**
+ * Demonstrates that {@link HttpServletRequest#authenticate(HttpServletResponse)} will send the user to the log in
+ * page configured within Spring Security if the user is not already authenticated.
+ *
+ * @param request
+ * @param response
+ * @return
+ * @throws ServletException
+ * @throws IOException
+ */
+ @RequestMapping("/authenticate")
+ public String authenticate(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
+ boolean authenticate = request.authenticate(response);
+ return authenticate ? "index" : null;
+ }
+
+ /**
+ * Demonstrates that you can authenticate with Spring Security using
+ * {@link HttpServletRequest#login(String, String)}.
+ *
+ * <p>
+ * If we fail to authenticate, a {@link ServletException} is thrown that wraps the original
+ * {@link AuthenticationException} from Spring Security. This means we can catch the {@link ServletException} to
+ * display the error message. Alternatively, we could allow the {@link ServletException} to propegate and Spring
+ * Security's {@link ExceptionTranslationFilter} would catch it and process it appropriately.
+ * </p>
+ * <p>
+ * In this method we choose to use Spring MVC's {@link ModelAttribute} to make things easier for our form. However,
+ * this is not necessary. We could have just as easily obtained the request parameters from the
+ * {@link HttpServletRequest} object. Remember all of these examples would work in a standard {@link Servlet} or
+ * anything with access to the {@link HttpServletRequest} and {@link HttpServletResponse}.
+ * </p>
+ *
+ * @param request
+ * @param response
+ * @param loginForm
+ * @param result
+ * @return
+ * @throws ServletException
+ */
+ @RequestMapping(value = "/login", method = RequestMethod.POST)
+ public String login(HttpServletRequest request, HttpServletResponse response,
+ @ModelAttribute LoginForm loginForm, BindingResult result) throws ServletException {
+ try {
+ request.login(loginForm.getUsername(), loginForm.getPassword());
+ } catch(ServletException authenticationFailed) {
+ result.rejectValue(null, "authentication.failed", authenticationFailed.getMessage());
+ return "login";
+ }
+ return "redirect:/";
+ }
+
+ /**
+ * Demonstrates that invoking {@link HttpServletRequest#logout()} will log the user out. Note that the response does
+ * not get processed, so you need to write something to the response.
+ * @param request
+ * @param response
+ * @param redirect
+ * @return
+ * @throws ServletException
+ */
+ @RequestMapping("/logout")
+ public String logout(HttpServletRequest request, HttpServletResponse response, RedirectAttributes redirect) throws ServletException {
+ request.logout();
+ return "redirect:/";
+ }
+
+ /**
+ * Demonstrates Spring Security with {@link AsyncContext#start(Runnable)}. Spring Security will automatically
+ * transfer the {@link SecurityContext} from the thread that {@link AsyncContext#start(Runnable)} is invoked to the
+ * new Thread that invokes the {@link Runnable}.
+ * @param request
+ * @param response
+ */
+ @RequestMapping("/async")
+ public void asynch(HttpServletRequest request, HttpServletResponse response) {
+ final AsyncContext async = request.startAsync();
+ async.start(new Runnable() {
+ public void run() {
+ Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
+ try {
+ final HttpServletResponse asyncResponse = (HttpServletResponse) async.getResponse();
+ asyncResponse.setStatus(HttpServletResponse.SC_OK);
+ asyncResponse.getWriter().write(String.valueOf(authentication));
+ async.complete();
+ } catch(Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+ });
+ }
+
+ /**
+ * Demonstrates that Spring Security automatically populates {@link HttpServletRequest#getRemoteUser()} with the
+ * current username.
+ * @param request
+ * @return
+ */
+ @ModelAttribute("remoteUser")
+ public String remoteUser(HttpServletRequest request) {
+ return request.getRemoteUser();
+ }
+
+ /**
+ * Demonstrates that Spring Security automatically populates {@link HttpServletRequest#getUserPrincipal()} with the
+ * {@link Authentication} that is present on {@link SecurityContextHolder#getContext()}
+ * @param request
+ * @return
+ */
+ @ModelAttribute("userPrincipal")
+ public Principal userPrincipal(HttpServletRequest request) {
+ return request.getUserPrincipal();
+ }
+
+ /**
+ * Spring MVC will automatically resolve any object that implements {@link Principal} using
+ * {@link HttpServletRequest#getUserPrincipal()}. This means you can easily resolve the {@link Authentication} just
+ * by adding it as an argument to your MVC controller. Alternatively, you could also have an argument of type
+ * {@link Principal} which would not couple your controller to Spring Security.
+ * @param authentication
+ * @return
+ */
+ @ModelAttribute
+ public Authentication authentication(Authentication authentication) {
+ return authentication;
+ }
+
+ @RequestMapping("/")
+ public String welcome() {
+ return "index";
+ }
+
+ @RequestMapping(value = "/login", method = RequestMethod.GET)
+ public String login(@ModelAttribute LoginForm loginForm) {
+ return "login";
+ }
+}
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<b:beans xmlns:b="http://www.springframework.org/schema/beans"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns="http://www.springframework.org/schema/security"
+ xmlns:p="http://www.springframework.org/schema/p"
+ xmlns:util="http://www.springframework.org/schema/util"
+ xsi:schemaLocation="http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.1.xsd
+ http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
+ http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.0.xsd">
+
+ <http auto-config="true" use-expressions="true">
+ <intercept-url pattern="/**" access="permitAll"/>
+ </http>
+
+ <authentication-manager>
+ <authentication-provider>
+ <user-service>
+ <user name="user" password="password" authorities="ROLE_USER" />
+ <user name="admin" password="password" authorities="ROLE_USER,ROLE_ADMIN"/>
+ </user-service>
+ </authentication-provider>
+ </authentication-manager>
+</b:beans>
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<b:beans xmlns="http://www.springframework.org/schema/mvc"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:b="http://www.springframework.org/schema/beans"
+ xmlns:p="http://www.springframework.org/schema/p"
+ xmlns:context="http://www.springframework.org/schema/context"
+ xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd
+ http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
+ http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd">
+
+ <context:component-scan base-package="org.springframework.security.samples.servletapi.mvc" />
+
+ <!-- Enables the Spring MVC @Controller programming model -->
+ <annotation-driven/>
+
+ <!-- Handles HTTP GET requests for /resources/** by efficiently serving up static resources in the ${webappRoot}/resources/ directory -->
+ <resources mapping="/resources/**" location="/resources/" />
+
+ <!-- Resolves views selected for rendering by @Controllers to .jsp resources in the /WEB-INF/views directory -->
+ <b:bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"
+ p:prefix="/WEB-INF/views/"
+ p:suffix=".jsp" />
+
+</b:beans>
@@ -0,0 +1,44 @@
+<%@ taglib prefix="sec" uri="http://www.springframework.org/security/tags" %>
+<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
+<html>
+<head>
+<title>Welcome</title>
+</head>
+<body>
+ <h1>Home Page</h1>
+ <p>
+ Anyone can view this page.
+ </p>
+
+ <sec:authorize access="authenticated" var="authenticated"/>
+ <c:if test="${authenticated}">
+ <p>You are currently authenticated</p>
+ <dl>
+ <dt>HttpServletRequest.getRemoteUser()</dt>
+ <dd><c:out value="${remoteUser}"/></dd>
+ <dt>HttpServletRequest.getUserPrincipal()</dt>
+ <dd><c:out value="${userPrincipal}"/></dd>
+ <dt>Authentication</dt>
+ <dd><c:out value="${authentication}"/></dd>
+ </dl>
+ </c:if>
+ <ul>
+ <li>
+ <a href="<c:url value="/authenticate"/>">HttpServletRequest.authenticate(HttpServletResponse)</a>
+ - if you are authenticated already will simply return true. Otherwise, will redirect you to the log in page configured in your Spring Security configuration.
+ </li>
+ <li>
+ <a href="<c:url value="/async"/>">AsyncContext.start(Runnable)</a>
+ - will automatically transfer the current SecurityContext to the new Thread
+ </li>
+ <c:choose>
+ <c:when test="${authenticated}">
+ <li><a href="<c:url value="/logout"/>">HttpServletRequest.logout()</a></li>
+ </c:when>
+ <c:otherwise>
+ <li><a href="<c:url value="/login"/>">Fill out log in form</a> - allows the user to invoke HttpServletRequest.login(String,String)</li>
+ </c:otherwise>
+ </c:choose>
+ </ul>
+</body>
+</html>
@@ -0,0 +1,26 @@
+<%@ taglib prefix="sec" uri="http://www.springframework.org/security/tags" %>
+<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
+<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
+<html>
+<head>
+<title>Please Log In</title>
+</head>
+<body>
+ <h1>Please Log In</h1>
+ <p>This page demonstrates the use of HttpServletRequest.login(String,String) integration with Spring Security.</p>
+ <form:form action="./login" method="post" modelAttribute="loginForm">
+ <form:errors/>
+ <p>
+ <label for="username">Username</label>
+ <form:input path="username"/>
+ </p>
+ <p>
+ <label for="password">Password</label>
+ <form:password path="password"/>
+ </p>
+ <p>
+ <input type="submit" value="Log In"/>
+ </p>
+ </form:form>
+</body>
+</html>
Oops, something went wrong.

0 comments on commit 22e333b

Please sign in to comment.