From 4b43cf3f50a6c3f1fd6da5ce4993cbee80d21746 Mon Sep 17 00:00:00 2001 From: Rob Winch Date: Thu, 3 Oct 2013 14:15:09 -0500 Subject: [PATCH] SEC-2349: Convert Reference to Asciidoctor --- build.gradle | 2 - buildSrc/build.gradle | 19 + .../gradle/AsciidoctorBackend.groovy | 45 + .../gradle/AsciidoctorPlugin.groovy | 32 + .../asciidoctor/gradle/AsciidoctorTask.groovy | 201 + .../org/asciidoctor/gradle/InputHandler.java | 336 + .../gradle-plugins/asciidoctor.properties | 1 + buildSrc/src/main/resources/docbook-xsl.zip | Bin 0 -> 32346 bytes docs/docs.gradle | 37 +- docs/guides/build.gradle | 11 +- docs/manual/src/asciidoctor/Guardfile | 12 + .../images/Authentication.gif | Bin .../images/access-decision-voting.graffle | Bin .../images/access-decision-voting.png | Bin .../images/after-invocation.graffle | Bin .../images/after-invocation.png | Bin .../{docbook => asciidoctor}/images/note.png | Bin .../images/s2-banner-rhs.png | Bin .../images/s2_box_logo.png | Bin .../images/security-interception.graffle | Bin .../images/security-interception.png | Bin .../{docbook => asciidoctor}/images/tip.png | Bin docs/manual/src/asciidoctor/index.adoc | 7579 +++++++++++++++++ .../manual/src/docbook/anon-auth-provider.xml | 138 - .../manual/src/docbook/appendix-db-schema.xml | 197 - .../src/docbook/appendix-dependencies.xml | 456 - .../manual/src/docbook/appendix-namespace.xml | 2293 ----- .../src/docbook/authorization-common.xml | 345 - .../src/docbook/basic-and-digest-auth.xml | 169 - docs/manual/src/docbook/cas-auth-provider.xml | 567 -- docs/manual/src/docbook/channel-security.xml | 140 - docs/manual/src/docbook/class-index-html.xsl | 43 - docs/manual/src/docbook/classindex.pl | 127 - docs/manual/src/docbook/community.xml | 48 - docs/manual/src/docbook/core-filters.xml | 339 - docs/manual/src/docbook/core-services.xml | 318 - docs/manual/src/docbook/crypto.xml | 138 - docs/manual/src/docbook/csrf.xml | 331 - docs/manual/src/docbook/domain-acls.xml | 294 - docs/manual/src/docbook/el-access.xml | 297 - .../src/docbook/form-authentication.xml | 68 - docs/manual/src/docbook/headers.xml | 436 - docs/manual/src/docbook/html-titlepage.xml | 61 - docs/manual/src/docbook/index-classes.xsl | 19 - docs/manual/src/docbook/index.xml | 181 - docs/manual/src/docbook/introduction.xml | 308 - .../manual/src/docbook/jaas-auth-provider.xml | 232 - .../manual/src/docbook/ldap-auth-provider.xml | 432 - docs/manual/src/docbook/namespace-config.xml | 1029 --- docs/manual/src/docbook/new-3-1.xml | 67 - docs/manual/src/docbook/packagecheck.sh | 3 - docs/manual/src/docbook/pdf-titlepage.xml | 101 - docs/manual/src/docbook/preauth.xml | 192 - .../docbook/remember-me-authentication.xml | 180 - .../src/docbook/runas-auth-provider.xml | 97 - docs/manual/src/docbook/samples.xml | 145 - docs/manual/src/docbook/secured-objects.xml | 154 - .../src/docbook/security-filter-chain.xml | 338 - docs/manual/src/docbook/servlet-api.xml | 167 - docs/manual/src/docbook/session-mgmt.xml | 181 - docs/manual/src/docbook/taglibs.xml | 117 - .../manual/src/docbook/technical-overview.xml | 719 -- .../manual/src/docbook/x509-auth-provider.xml | 100 - docs/manual/src/resources/css/highlight.css | 35 - docs/manual/src/resources/css/manual.css | 69 - docs/manual/src/xsl/html-custom.xsl | 145 - docs/manual/src/xsl/html-single-custom.xsl | 142 - docs/manual/src/xsl/pdf-custom.xsl | 503 -- 68 files changed, 8255 insertions(+), 12481 deletions(-) create mode 100755 buildSrc/src/main/groovy/org/asciidoctor/gradle/AsciidoctorBackend.groovy create mode 100755 buildSrc/src/main/groovy/org/asciidoctor/gradle/AsciidoctorPlugin.groovy create mode 100755 buildSrc/src/main/groovy/org/asciidoctor/gradle/AsciidoctorTask.groovy create mode 100644 buildSrc/src/main/groovy/org/asciidoctor/gradle/InputHandler.java create mode 100644 buildSrc/src/main/resources/META-INF/gradle-plugins/asciidoctor.properties create mode 100644 buildSrc/src/main/resources/docbook-xsl.zip create mode 100644 docs/manual/src/asciidoctor/Guardfile rename docs/manual/src/{docbook => asciidoctor}/images/Authentication.gif (100%) rename docs/manual/src/{docbook => asciidoctor}/images/access-decision-voting.graffle (100%) rename docs/manual/src/{docbook => asciidoctor}/images/access-decision-voting.png (100%) rename docs/manual/src/{docbook => asciidoctor}/images/after-invocation.graffle (100%) rename docs/manual/src/{docbook => asciidoctor}/images/after-invocation.png (100%) rename docs/manual/src/{docbook => asciidoctor}/images/note.png (100%) rename docs/manual/src/{docbook => asciidoctor}/images/s2-banner-rhs.png (100%) rename docs/manual/src/{docbook => asciidoctor}/images/s2_box_logo.png (100%) rename docs/manual/src/{docbook => asciidoctor}/images/security-interception.graffle (100%) rename docs/manual/src/{docbook => asciidoctor}/images/security-interception.png (100%) rename docs/manual/src/{docbook => asciidoctor}/images/tip.png (100%) create mode 100644 docs/manual/src/asciidoctor/index.adoc delete mode 100644 docs/manual/src/docbook/anon-auth-provider.xml delete mode 100644 docs/manual/src/docbook/appendix-db-schema.xml delete mode 100644 docs/manual/src/docbook/appendix-dependencies.xml delete mode 100644 docs/manual/src/docbook/appendix-namespace.xml delete mode 100644 docs/manual/src/docbook/authorization-common.xml delete mode 100644 docs/manual/src/docbook/basic-and-digest-auth.xml delete mode 100644 docs/manual/src/docbook/cas-auth-provider.xml delete mode 100644 docs/manual/src/docbook/channel-security.xml delete mode 100644 docs/manual/src/docbook/class-index-html.xsl delete mode 100755 docs/manual/src/docbook/classindex.pl delete mode 100644 docs/manual/src/docbook/community.xml delete mode 100644 docs/manual/src/docbook/core-filters.xml delete mode 100644 docs/manual/src/docbook/core-services.xml delete mode 100644 docs/manual/src/docbook/crypto.xml delete mode 100644 docs/manual/src/docbook/csrf.xml delete mode 100644 docs/manual/src/docbook/domain-acls.xml delete mode 100644 docs/manual/src/docbook/el-access.xml delete mode 100644 docs/manual/src/docbook/form-authentication.xml delete mode 100644 docs/manual/src/docbook/headers.xml delete mode 100644 docs/manual/src/docbook/html-titlepage.xml delete mode 100644 docs/manual/src/docbook/index-classes.xsl delete mode 100644 docs/manual/src/docbook/index.xml delete mode 100644 docs/manual/src/docbook/introduction.xml delete mode 100644 docs/manual/src/docbook/jaas-auth-provider.xml delete mode 100644 docs/manual/src/docbook/ldap-auth-provider.xml delete mode 100644 docs/manual/src/docbook/namespace-config.xml delete mode 100644 docs/manual/src/docbook/new-3-1.xml delete mode 100755 docs/manual/src/docbook/packagecheck.sh delete mode 100644 docs/manual/src/docbook/pdf-titlepage.xml delete mode 100644 docs/manual/src/docbook/preauth.xml delete mode 100644 docs/manual/src/docbook/remember-me-authentication.xml delete mode 100644 docs/manual/src/docbook/runas-auth-provider.xml delete mode 100644 docs/manual/src/docbook/samples.xml delete mode 100644 docs/manual/src/docbook/secured-objects.xml delete mode 100644 docs/manual/src/docbook/security-filter-chain.xml delete mode 100644 docs/manual/src/docbook/servlet-api.xml delete mode 100644 docs/manual/src/docbook/session-mgmt.xml delete mode 100644 docs/manual/src/docbook/taglibs.xml delete mode 100644 docs/manual/src/docbook/technical-overview.xml delete mode 100644 docs/manual/src/docbook/x509-auth-provider.xml delete mode 100644 docs/manual/src/resources/css/highlight.css delete mode 100644 docs/manual/src/resources/css/manual.css delete mode 100644 docs/manual/src/xsl/html-custom.xsl delete mode 100644 docs/manual/src/xsl/html-single-custom.xsl delete mode 100644 docs/manual/src/xsl/pdf-custom.xsl diff --git a/build.gradle b/build.gradle index 166e52d3eb..7d159b7452 100644 --- a/build.gradle +++ b/build.gradle @@ -3,7 +3,6 @@ import groovy.text.SimpleTemplateEngine buildscript { repositories { maven { url "http://repo.springsource.org/plugins-release" } - maven { url "http://dl.bintray.com/content/aalmiray/asciidoctor" } maven { url "http://jcenter.bintray.com"} } dependencies { @@ -11,7 +10,6 @@ buildscript { classpath("org.springframework.build.gradle:docbook-reference-plugin:0.2.7") classpath("org.springframework.build.gradle:bundlor-plugin:0.1.2") classpath("org.gradle.api.plugins:gradle-tomcat-plugin:0.9.8") - classpath("org.asciidoctor:asciidoctor-gradle-plugin:0.4.1") classpath('me.champeau.gradle:gradle-javadoc-hotfix-plugin:0.1') } } diff --git a/buildSrc/build.gradle b/buildSrc/build.gradle index 04570ae8ae..0ac2b0dfca 100644 --- a/buildSrc/build.gradle +++ b/buildSrc/build.gradle @@ -12,6 +12,10 @@ repositories { } } +dependencies { + compile gradleApi() +} + // GAE dependencies { compile 'com.google.appengine:appengine-tools-sdk:1.4.2' @@ -27,6 +31,21 @@ dependencies { 'net.sourceforge.saxon:saxon:9.1.0.8' } +dependencies { + compile('org.asciidoctor:asciidoctor-java-integration:0.1.3') { + exclude group: 'rubygems', module :'haml' + exclude group: 'rubygems', module :'asciidoctor' + exclude group: 'rubygems', module :'coderay' + exclude group: 'rubygems', module :'tilt' + exclude group: 'rubygems', module :'erubis' + exclude group: 'rubygems', module :'slim' + } + compile 'org.apache.avalon.framework:avalon-framework-api:4.3.1' + compile 'org.apache.avalon.framework:avalon-framework-impl:4.3.1' + compile 'org.apache.xmlgraphics:fop:1.1' + runtime 'net.sf.xslthl:xslthl:2.1.0' +} + task ide(type: Copy) { from configurations.runtime into 'ide' diff --git a/buildSrc/src/main/groovy/org/asciidoctor/gradle/AsciidoctorBackend.groovy b/buildSrc/src/main/groovy/org/asciidoctor/gradle/AsciidoctorBackend.groovy new file mode 100755 index 0000000000..f45a789619 --- /dev/null +++ b/buildSrc/src/main/groovy/org/asciidoctor/gradle/AsciidoctorBackend.groovy @@ -0,0 +1,45 @@ +/* + * Copyright 2012-2013 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.asciidoctor.gradle + +/** + * Supported backends. + * + * @author Benjamin Muschko + */ +enum AsciidoctorBackend { + HTML5('html5'), DOCBOOK('docbook'), PDF('pdf') + + private final static Map ALL_BACKENDS + private final String id + + static { + ALL_BACKENDS = values().collectEntries{ [it.id, it] }.asImmutable() + } + + private AsciidoctorBackend(String id) { + this.id = id + } + + String getId() { + id + } + + static boolean isSupported(String name) { + ALL_BACKENDS.containsKey(name) + } +} diff --git a/buildSrc/src/main/groovy/org/asciidoctor/gradle/AsciidoctorPlugin.groovy b/buildSrc/src/main/groovy/org/asciidoctor/gradle/AsciidoctorPlugin.groovy new file mode 100755 index 0000000000..4c56b8167f --- /dev/null +++ b/buildSrc/src/main/groovy/org/asciidoctor/gradle/AsciidoctorPlugin.groovy @@ -0,0 +1,32 @@ +/* + * Copyright 2012-2013 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.asciidoctor.gradle + +import groovy.lang.Closure; + +import org.gradle.api.Plugin +import org.gradle.api.Project + +/** + * @author Noam Tenne + * @author Andres Almiray + */ +class AsciidoctorPlugin implements Plugin { + void apply(Project project) { + project.task('asciidoctor', type: AsciidoctorTask, group: 'Documentation') + } +} diff --git a/buildSrc/src/main/groovy/org/asciidoctor/gradle/AsciidoctorTask.groovy b/buildSrc/src/main/groovy/org/asciidoctor/gradle/AsciidoctorTask.groovy new file mode 100755 index 0000000000..8536d7b5e1 --- /dev/null +++ b/buildSrc/src/main/groovy/org/asciidoctor/gradle/AsciidoctorTask.groovy @@ -0,0 +1,201 @@ +/* + * Copyright 2012-2013 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.asciidoctor.gradle + +import org.asciidoctor.gradle.* + + +import org.apache.commons.io.IOUtils +import org.asciidoctor.Asciidoctor +import org.gradle.api.DefaultTask +import org.gradle.api.GradleException +import org.gradle.api.InvalidUserDataException +import org.gradle.api.tasks.* + +import javax.xml.transform.* +import javax.xml.transform.stream.* +import javax.xml.transform.sax.* +import org.apache.fop.apps.FopFactory +import org.apache.fop.apps.Fop +import org.apache.fop.apps.MimeConstants + + +class AsciidoctorTask extends DefaultTask { + @InputFile File sourceDocument + @Input Map options = [:] + + @Optional @OutputDirectory File outputDir + @Optional @Input List backends + + AsciidoctorTask() { + sourceDocument = project.file("src/asciidoctor/index.adoc") + outputDir = project.file("${project.buildDir}/asciidoctor") + backends = [AsciidoctorBackend.HTML5.id] + } + + @TaskAction + void render() { + + Asciidoctor asciidoctor = Asciidoctor.Factory.create() + + for(backend in backends) { + boolean isPdf = backend == AsciidoctorBackend.PDF.id + String asciidoctorBackend = isPdf ? AsciidoctorBackend.DOCBOOK.id : backend + + File distDir = new File("${outputDir}/dist/$backend") + File workingDir = new File("${outputDir}/work/$backend") + + [workingDir,distDir]*.mkdirs() + + try { + asciidoctor.renderFile(sourceDocument, mergedOptions(options, isPdf ? workingDir : distDir, asciidoctorBackend)) + + if(isPdf) { + generatePdf(workingDir,distDir) + } else { + project.copy { + from "${sourceDocument.parent}/images" + into "${distDir}/images/" + } + } + } catch (Exception e) { + throw new GradleException('Error running Asciidoctor on single source '+asciidoctorBackend, e) + } + } + } + + private void generatePdf(File workingDir, File distDir) { + String docbookXmlUrl = 'http://maven-us.nuxeo.org/nexus/content/repositories/public/docbook/docbook-xml/4.5/docbook-xml-4.5.jar' + String docbookXslUrl = 'http://downloads.sourceforge.net/project/docbook/docbook-xsl-ns/1.78.1/docbook-xsl-ns-1.78.1.zip' + + File docbookXmlFile = downloadFile(docbookXmlUrl) + File docbookXslFile = downloadFile(docbookXslUrl) + + project.copy { + from "src/asciidoctor/images" + into "${workingDir}/images/" + } + + project.copy { + from project.zipTree(docbookXmlFile) + into "$workingDir/docbook" + } + + project.copy { + from(project.zipTree(docbookXslFile)) { + eachFile { details -> + details.path = details.path.substring(details.relativePath.segments[0].length()) + } + } + into "$workingDir/docbook/" + } + + unzipDockbookXsl(workingDir) + + def outputUri = workingDir.toURI().toASCIIString() + + Vector params = new Vector() + params.add("highlight.xslthl.config") + params.add(outputUri + "docbook-xsl/xslthl-config.xml") + params.add("admon.graphics.path") + params.add(outputUri + "docbook/images/") + params.add("callout.graphics.path") + params.add(outputUri + "docbook/images/callouts/") + params.add("img.src.path") + params.add(outputUri) + params.add("fop-output-format") + params.add("application/pdf") + params.add("fop-version") + params.add("1.1") + + File outputFile = new File("${distDir}/", sourceDocument.name.replaceAll("\\..*", ".pdf")) + File docbookFile = new File("$workingDir/",sourceDocument.name.replaceAll("\\..*", ".xml")) + File xsltFile = new File("${workingDir}/docbook-xsl/fo-pdf.xsl") + + InputHandler handler = new InputHandler(docbookFile, xsltFile, params) + + FopFactory fopFactory = FopFactory.newInstance(); // Reuse the FopFactory if possible! + fopFactory.setUserConfig(new File("${workingDir}/docbook-xsl/fop-config.xml")) + // do the following for each new rendering run + def foUserAgent = fopFactory.newFOUserAgent(); + + handler.createCatalogResolver(foUserAgent) + + def out = new java.io.BufferedOutputStream( + new java.io.FileOutputStream(outputFile)); + + foUserAgent.setOutputFile(outputFile); + + try { + handler.renderTo(foUserAgent, MimeConstants.MIME_PDF, out) + } finally { + IOUtils.closeQuietly(out) + } + } + + private void unzipDockbookXsl(def installDir) { + def docbookXslResourceName = 'docbook-xsl.zip' + def docbookXslInputStream = this.class.classLoader.getResourceAsStream(docbookXslResourceName) + if (docbookXslInputStream == null) { + throw new GradleException("could not find ${docbookXslResourceName} on the classpath"); + } + // the file is a jar:file - write it to disk first + File docbookXslOutputFile = new File("${installDir}/downloads/${docbookXslResourceName}") + docbookXslOutputFile.parentFile.mkdirs() + IOUtils.copy(docbookXslInputStream, new FileOutputStream(docbookXslOutputFile)) + project.copy { + from project.zipTree(docbookXslOutputFile) + into "${installDir}/" + } + } + + private File downloadFile(String url) { + def home = System.getProperty("user.home") + File destinationFile = new File("${home}/.fopdf/downloads", url.split("/")[-1]) + destinationFile.parentFile.mkdirs() + + if(!destinationFile.exists()) { + logger.info("Downloading " + url + " to "+ destinationFile + "...") + destinationFile.bytes = new URL(url).bytes + } + destinationFile + } + + private static Map mergedOptions(Map options, File outputDir, String backend) { + Map mergedOptions = [:] + mergedOptions.putAll(options) + mergedOptions.in_place = false + mergedOptions.safe = 0i + mergedOptions.to_dir = outputDir.absolutePath + Map attributes = mergedOptions.get('attributes', [:]) + attributes.backend = backend + + // Issue #14 force GString -> String as jruby will fail + // to find an exact match when invoking Asciidoctor + for (entry in mergedOptions) { + if (entry.value instanceof CharSequence) { + mergedOptions[entry.key] = entry.value.toString() + } + } + for (entry in attributes) { + if (entry.value instanceof CharSequence) { + attributes[entry.key] = entry.value.toString() + } + } + mergedOptions + } +} \ No newline at end of file diff --git a/buildSrc/src/main/groovy/org/asciidoctor/gradle/InputHandler.java b/buildSrc/src/main/groovy/org/asciidoctor/gradle/InputHandler.java new file mode 100644 index 0000000000..21d66392f5 --- /dev/null +++ b/buildSrc/src/main/groovy/org/asciidoctor/gradle/InputHandler.java @@ -0,0 +1,336 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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. + */ + +/* $Id$ */ + +package org.asciidoctor.gradle; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.Vector; + +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.parsers.SAXParserFactory; +import javax.xml.transform.ErrorListener; +import javax.xml.transform.Result; +import javax.xml.transform.Source; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerException; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.URIResolver; +import javax.xml.transform.sax.SAXResult; +import javax.xml.transform.sax.SAXSource; +import javax.xml.transform.stream.StreamResult; +import javax.xml.transform.stream.StreamSource; + +import org.xml.sax.EntityResolver; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; +import org.xml.sax.XMLReader; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import org.apache.fop.ResourceEventProducer; +import org.apache.fop.apps.FOPException; +import org.apache.fop.apps.FOUserAgent; +import org.apache.fop.apps.Fop; +import org.apache.fop.apps.FopFactory; +import org.apache.fop.render.awt.viewer.Renderable; + +/** + * Class for handling files input from command line + * either with XML and XSLT files (and optionally xsl + * parameters) or FO File input alone. + */ +public class InputHandler implements ErrorListener, Renderable { + + /** original source file */ + protected File sourcefile; + private File stylesheet; // for XML/XSLT usage + private Vector xsltParams; // for XML/XSLT usage + private EntityResolver entityResolver = null; + private URIResolver uriResolver = null; + + /** the logger */ + protected Log log = LogFactory.getLog(InputHandler.class); + + /** + * Constructor for XML->XSLT->FO input + * + * @param xmlfile XML file + * @param xsltfile XSLT file + * @param params Vector of command-line parameters (name, value, + * name, value, ...) for XSL stylesheet, null if none + */ + public InputHandler(File xmlfile, File xsltfile, Vector params) { + if(!xsltfile.exists()) { + throw new RuntimeException("Couldn't find "+ xsltfile); + } + sourcefile = xmlfile; + stylesheet = xsltfile; + xsltParams = params; + } + + /** + * Constructor for FO input + * @param fofile the file to read the FO document. + */ + public InputHandler(File fofile) { + sourcefile = fofile; + } + + /** + * Generate a document, given an initialized Fop object + * @param userAgent the user agent + * @param outputFormat the output format to generate (MIME type, see MimeConstants) + * @param out the output stream to write the generated output to (may be null if not applicable) + * @throws FOPException in case of an error during processing + */ + public void renderTo(FOUserAgent userAgent, String outputFormat, OutputStream out) + throws FOPException { + + FopFactory factory = userAgent.getFactory(); + Fop fop; + if (out != null) { + fop = factory.newFop(outputFormat, userAgent, out); + } else { + fop = factory.newFop(outputFormat, userAgent); + } + + // if base URL was not explicitly set in FOUserAgent, obtain here + if (fop.getUserAgent().getBaseURL() == null && sourcefile != null) { + String baseURL = null; + + try { + baseURL = new File(sourcefile.getAbsolutePath()) + .getParentFile().toURI().toURL().toExternalForm(); + } catch (Exception e) { + baseURL = ""; + } + fop.getUserAgent().setBaseURL(baseURL); + } + + // Resulting SAX events (the generated FO) must be piped through to FOP + Result res = new SAXResult(fop.getDefaultHandler()); + + transformTo(res); + } + + /** {@inheritDoc} */ + public void renderTo(FOUserAgent userAgent, String outputFormat) throws FOPException { + renderTo(userAgent, outputFormat, null); + } + + /** + * In contrast to render(Fop) this method only performs the XSLT stage and saves the + * intermediate XSL-FO file to the output file. + * @param out OutputStream to write the transformation result to. + * @throws FOPException in case of an error during processing + */ + public void transformTo(OutputStream out) throws FOPException { + Result res = new StreamResult(out); + transformTo(res); + } + + /** + * Creates a Source for the main input file. Processes XInclude if + * available in the XML parser. + * + * @return the Source for the main input file + */ + protected Source createMainSource() { + Source source; + InputStream in; + String uri; + if (this.sourcefile != null) { + try { + in = new java.io.FileInputStream(this.sourcefile); + uri = this.sourcefile.toURI().toASCIIString(); + } catch (FileNotFoundException e) { + //handled elsewhere + return new StreamSource(this.sourcefile); + } + } else { + in = System.in; + uri = null; + } + try { + InputSource is = new InputSource(in); + is.setSystemId(uri); + XMLReader xr = getXMLReader(); + if (entityResolver != null) { + xr.setEntityResolver(entityResolver); + } + source = new SAXSource(xr, is); + } catch (SAXException e) { + if (this.sourcefile != null) { + source = new StreamSource(this.sourcefile); + } else { + source = new StreamSource(in, uri); + } + } catch (ParserConfigurationException e) { + if (this.sourcefile != null) { + source = new StreamSource(this.sourcefile); + } else { + source = new StreamSource(in, uri); + } + } + return source; + } + + /** + * Creates a catalog resolver and uses it for XML parsing and XSLT URI resolution. + * Tries the Apache Commons Resolver, and if unsuccessful, + * tries the same built into Java 6. + * @param userAgent the user agent instance + */ + public void createCatalogResolver(FOUserAgent userAgent) { + String[] classNames = new String[] { + "org.apache.xml.resolver.tools.CatalogResolver", + "com.sun.org.apache.xml.internal.resolver.tools.CatalogResolver"}; + ResourceEventProducer eventProducer + = ResourceEventProducer.Provider.get(userAgent.getEventBroadcaster()); + Class resolverClass = null; + for (int i = 0; i < classNames.length && resolverClass == null; ++i) { + try { + resolverClass = Class.forName(classNames[i]); + } catch (ClassNotFoundException e) { + // No worries + } + } + if (resolverClass == null) { + eventProducer.catalogResolverNotFound(this); + return; + } + try { + entityResolver = (EntityResolver) resolverClass.newInstance(); + uriResolver = (URIResolver) resolverClass.newInstance(); + } catch (InstantiationException e) { + log.error("Error creating the catalog resolver: " + e.getMessage()); + eventProducer.catalogResolverNotCreated(this, e.getMessage()); + } catch (IllegalAccessException e) { + log.error("Error creating the catalog resolver: " + e.getMessage()); + eventProducer.catalogResolverNotCreated(this, e.getMessage()); + } + } + + /** + * Creates a Source for the selected stylesheet. + * + * @return the Source for the selected stylesheet or null if there's no stylesheet + */ + protected Source createXSLTSource() { + Source xslt = null; + if (this.stylesheet != null) { + if (entityResolver != null) { + try { + InputSource is = new InputSource(this.stylesheet.getPath()); + XMLReader xr = getXMLReader(); + xr.setEntityResolver(entityResolver); + xslt = new SAXSource(xr, is); + } catch (SAXException e) { + // return StreamSource + } catch (ParserConfigurationException e) { + // return StreamSource + } + } + if (xslt == null) { + xslt = new StreamSource(this.stylesheet); + } + } + return xslt; + } + + private XMLReader getXMLReader() throws ParserConfigurationException, SAXException { + SAXParserFactory spf = SAXParserFactory.newInstance(); + spf.setFeature("http://xml.org/sax/features/namespaces", true); + spf.setFeature("http://apache.org/xml/features/xinclude", true); + XMLReader xr = spf.newSAXParser().getXMLReader(); + return xr; + } + + /** + * Transforms the input document to the input format expected by FOP using XSLT. + * @param result the Result object where the result of the XSL transformation is sent to + * @throws FOPException in case of an error during processing + */ + protected void transformTo(Result result) throws FOPException { + try { + // Setup XSLT + System.setProperty("javax.xml.transform.TransformerFactory", "org.apache.xalan.processor.TransformerFactoryImpl"); + TransformerFactory factory = TransformerFactory.newInstance(); + if (uriResolver != null) { + factory.setURIResolver(uriResolver); + } + factory.setErrorListener(this); + Transformer transformer; + + Source xsltSource = createXSLTSource(); + if (xsltSource == null) { // FO Input + transformer = factory.newTransformer(); + } else { // XML/XSLT input + transformer = factory.newTransformer(xsltSource); + + // Set the value of parameters, if any, defined for stylesheet + if (xsltParams != null) { + for (int i = 0; i < xsltParams.size(); i += 2) { + transformer.setParameter((String) xsltParams.elementAt(i), + (String) xsltParams.elementAt(i + 1)); + } + } + } + transformer.setErrorListener(this); + + // Create a SAXSource from the input Source file + Source src = createMainSource(); + + // Start XSLT transformation and FOP processing + transformer.transform(src, result); + + } catch (Exception e) { + throw new FOPException(e); + } + } + + // --- Implementation of the ErrorListener interface --- + + /** + * {@inheritDoc} + */ + public void warning(TransformerException exc) { + log.warn(exc.getLocalizedMessage()); + } + + /** + * {@inheritDoc} + */ + public void error(TransformerException exc) { + log.error(exc.toString()); + } + + /** + * {@inheritDoc} + */ + public void fatalError(TransformerException exc) + throws TransformerException { + throw exc; + } + +} \ No newline at end of file diff --git a/buildSrc/src/main/resources/META-INF/gradle-plugins/asciidoctor.properties b/buildSrc/src/main/resources/META-INF/gradle-plugins/asciidoctor.properties new file mode 100644 index 0000000000..2f347513ee --- /dev/null +++ b/buildSrc/src/main/resources/META-INF/gradle-plugins/asciidoctor.properties @@ -0,0 +1 @@ +implementation-class=org.asciidoctor.gradle.AsciidoctorPlugin \ No newline at end of file diff --git a/buildSrc/src/main/resources/docbook-xsl.zip b/buildSrc/src/main/resources/docbook-xsl.zip new file mode 100644 index 0000000000000000000000000000000000000000..e0d6d7da09ba4ca14b2c5d555a08c36223de9f90 GIT binary patch literal 32346 zcmb5VbC7J`wzgTeZQHhO+qP}nwvAmjcbU6v+qSE|eQtOE@jHEQ-_sc}SFFg094l9j zF`qf#vEEdW1_prw_}6PeNLcv4PX6x$3;+&*iM_Fry}dQ9hqDd6stP0kaGt%a(!YkQ z2Q&a6$QdvIz<(VS{zgIh`#A`JxoRQd&q3CN20#FSa1a0h=)X~n4P6Xv?9J&sY;FE4 z$i%XY(!a*P1?fo^w8thy2)+46MV{8JC{?RbYb_pn?oV3K&@7jV%gA+A&=>()zWDrT z^k6?POhuxc0EN5l^@KMgOD|vVL(E+O!l|J>*B+l;T7gMI*n4$TzfRrR zAQPcYeYgt2s6n@H9t>A+7mhcROazE$^OxbawV!wv!lXXTsxm~lPDHCMr(~V475J%Ow2BMkg7R?;&8st|#KN$OyL0R>f;h$h=b3Y>O1Fd99d0W6g}DH0>}5{ zDqn>W#-F?7cz()#?WiYM1oi-0LFsGEX3#3CVp<_tQoq34kXh@-RsJ>hZ(OM>;6+&- zH;8+RmPGF0Nas|Bc|~LC*!Wt2{;=?2=_;nOk4_3}Dg?)0)* zl4OMU-#qzcW-ilaDFIVkVrxvr_|+?~nRKEl*9!CuK9+q@1fO6;LR`qv z(Q+wsR3Tpdo*S*dd`+g)eey^ke|-E8sOf3Zrm?At;H1bMH*rI{C2Dk$>$`^TZWl+Z zOVh(NED4I=C=BbN4L(*?{wVvUMEVo71`4rp9m=tn9pss{1yQ-D6~2Q}C2?&^rRpuG zPTa-8z(X{}Y6hEYVWM((0swYT_l`SZ;Q?)6vBXk83Sd7s_PKYb>wdaLG=-vro zY69K+0Vm+M#>1cY5OCES%g#A)`ywHJ0sJ#HD7fmN2Y)By5-I=y+P|m9-qzOM?te?n zmWHhJ1{*@pg?fPux0N|fRMG*5la1*oVm=dZ^LVp*f=*(EKmeeC^!tlu0E(!uLJF@f zS*1@s?Dd8&%{CpL>z7}q<2{HJGo@X3BEAQR2#GOS686nQ`DnlP%~!K~&*G<4HY#{7 zP=>8QJc0|+BP!OGM zc|?PTm>89j(pUftnDWQ0*q_QGOhlGo?3up#*Th35&joekmkzvTF>u11NKaVEpy-w4 zHr)h;Dhw4^FNb_O1*pX!Go_4vAdMs}dn$+Q6n8>cW}I^i_qLPdJ5h8pDN8#B9b{=1 zhloG1FV4=c9td@F2s78iuMmUUpIjG{8+XGMP4yC$!2N9I>qwJDdJ5{{(3ULnDKsKH z8Yl1lzOA#?M0{GpR_?7+!amRXvyMLQAIIO<*>j93JbrkX@*4~A@?s%8U~T^EH^B@gqi0va1n;cTV?vU3hWn?g!xnuXC>$ASdqjTpK>o@erQ8 zeh;|!jAmJ3I1*r53m_~^$yi8pLcnuKoLSVEd(4%$i6r$VVCe+KWeR=jQ_))jY0g#! zQqq!^pDo(jYp!GAREI#eiA+{<8ewe9yuL{^WUGXbj5NTS7_w#tMJTDznUtA`WC$b* zHO&-J8grR<)+@cvTM>Q`!QM{|D*_sC#XV=I5zvoQ4fzyV=fKU+-08aUCM319R>}&70M)v z%y`STPhFs`uy49NvCKB1u=!jIn_%4`^4xe?um$t5qGE#dw^Ivq?!I@eIx;6B(3E8luEV0{2ez|hEDzLye>u8> z+0IWF_M*VR=;vDX=EZX#G+*)23yO(hFZlhQRQo`&H>8`oCWDKzss{ONoMUwhll+pn zfeKgC0m=E$t^>^G(btWkA7r@3kKcS$m^V2Pl%C#iy}BNRZFHq8$n^D3p^xX*uqOR& zPGI&=O2K$7O-0m>IZ7kQ1fc2wn z5lmkxO7`7|jP}%~8uW~v(t30It9XpCbwtK}l8iv0P|3aLjvk86#k@r=o@$WD?gc%! zBfA4#inERHBDD!q`d0M#kL^B88j8N*?MwPVWU4EeZdOekiHY85y+8ZijG{}={qL#t zriE?we3yVsW+P>P&?RIU$jnCoVLstJ#> zWtDXItj=>mbQR(gZkG#^tz5qL_gw|5a_=27b<|l9uc9CC{c$n2N1a(fLVjTKbWZp; zS>a)NJ|9wR+yKWO2^3~MHzefFeMoJM__5-Ccx`fD0cWQDcySZy9?)@+BU51{Hy{@I z?e^Uu=^rm7`yD{2Kv0B{M@BQqucPvtC1fEs#*Y*Z$9u}iP@l&PCU@k~0Hc(CrCom% z;2u2M40*sslfeT>eNM*QTT+E`0b&U0WXucaCn3J(+m@{D8S&(77ZlhU0RGzyU`ZW_ zaxXcJzCe7wCy37=dJ=X;3B|GidJ5H~6BE!O_&p#A+hrU)>8R>}Er%Ys;4(DoR-L!o zpAtlv81l`4qDnTYtTEf&KfX{&>9YaQn1ZsM9~beM%w^9Tl#W30uLX|{(*T9mBmlm_ zmC(hRxx$!Re|ob_Y?)k)gtnd28S8;T!q7M)jjW(hUU3M?fVlQ*YsD3DI#Y_j>K(N9 zW21|FSlkexZfCMa4~z?O0Spj(vxA#=q{(DlJh%-sFc}c=IO$q)KyN`}Aa$$38X;v` z!Ml_EH5nuT$PYnQ}$=)_D+rnI1fX8#b3iw zS5T?N-~EDQL)ve~rqiiCsZX#tRk)}T`*vGMahkdE!h273^hJu7|GpN9hEGD<<|EP- znMf+c&hR|7wH>mf&tZLNtL%NkFE>k?kf^T&9M^L+Y2t-QM4(_M8Xt$^BSj0YFC|(^ z^fvkqzmu0zL6z?jAfdSnzf-XCMMmx)1WF_|AS1>ik70v6w!*Hl0I(2ahaNp?7V#_X z0k(Dx(7QVwDUU9x>6ihss-dX8sjpZ^=k5D(9z9*5vQ@F#JZ3nP2@Cv9%1J5Ffh@`gT!-}e;8NEZ zlWQ^TS~tO>0i0C^D7|A6_f6h1NFmr}=)%kjQwt4nBc=h~QD$Nn*k#{Ou*oGDf?aLq?Wy$qsduMu95I5|IX zB39X?Nu5GCaQC zC^6(-tNXCYnn{k~9FPqhE&1IhLALI{G4!Ozt9D}~QLL5ZC* zd1dr@Z6~iA^Ao%K>w}WDe5>0c_SN-8x^M3T5Q_)oBziv~aV3pmkC>60W7ne($jgY( z{GfqL@bAadPNRyoAfE)%oyb>!PpkxzGC3k%W5lOud@leYb|1mYHf$6YinQBVadw>G ziVp_QHz0c^zf4WK&ozexNL(~_Zm5#}JT|()mlQFBp){1K-mkGFRA>h*c595z1AZ>; zZGYOO<>$5Lc**mDmo1X^M9j)>0GLVLK;)Y!+vR*c{#-quhwmBTZr)9w+tdTgWI7t& zYra0%glw4nelP|NC!*yKBWD{4(c6{k=rc6#453a}BFmy*mYB6%l36#50eh+*zB)wY z4tqBYelOG6zo7?6+)1032Z(*X_U;F-u9`22k85N4>8pefxUeaW%w*heZffoLFF})K zpg9DU!Y|z1yuICf(RJeGa8B{g_QX=_E8NoP?9B1$ybLQjs!a!OuFv;iA6&F$cBbR3 z(reBHQw}dLKlk^~Ia5sHGqh4o;@h?Ub%vE<0+7Z=%E`;?YeqWG)@S5TNURe(R68h~JVEU9?D#a&elF_Ibq(8(dA;^7TWqk)G(?BQ(2XyTM0ABl1jC77dI5Z%LtlYMzA_c$texlv< zI(Dm!kL1BK)=)6|C)x%Hsv|jW`m#~1W-4bJDl6MBgKbw$B4}Y^rja*hD-G!wyh(Q^ zd7P11usmw&jiR1_l0*cZafdSKFs<5Saw38fO60ms)TonXEH$+NCI!Uk+vjgh#F!>; zBL~ne9&2)9Mh>0-bd!n#*%pG>MJku^%}yMvps20l#WKXG$yE1Ds7(rGA$=G&7iOqL zXA-Eh8S0IzGn;S^zVQQgz{--pJ7ozWoledAn#+9=0mD&7=47N)PVg&m{8^3R+U4fl6)x9Go^18HA zys~gM{I*eDbQ7BNel-!Pz!s_vV51v~y+iDLDqvxrkkrO1 zx5h0eIv>M+WQt)6J)NZz5?N@u)DWC2Nx`B{0aRXb5V;zsy4r`9D%f_Oj(}j!7k?%! zIZ3h^By&vXO1AGRq#rlCH12aef?O=EuYZ3W3W=YZH}PxW>GW6C__7e^=u?+15168yqWdh*Cn%-wR)dc%0gnIh` zk~!2Ctx08|7GJ07oRt!ru+!C1^HhM3B&T(g^neMxE3kKk-l>|WfL~uMjjxjc00lTc zTDq>B#r}GuSu%$mP7pddo8FZ7+VL&#YG-d`^uC-zM8+m`aDAuBu`&oJbn8$}J4S~` z0hq{PbCkG|$y@NW;Th4suZl1S5hFu|PsQ$gW#=ZnlJ|{=#v^T1aE5g?jg4Gsy{dWo z@qVQhZh0g+5HRxM%l^>CB=_f;Zfe0kQByTwrO9PhSj#n+7dc@z-YO<3GlK}7r3-O#&&_BfLjv>bp>ULuToNmIP;UI~ zefjw7RFjK~F6GZNdK{v9&_#VXM5)ye_$#WXik10AQPh}u(as2Ud~{Kp*#)H6k#68t z5FPKj&6LD0xt473yM`Dn-8LG-=T^yfCb0|W~`w^RQK2hH6H>_bL zH%we~HqU6xk|}G-BaSHpG{SeEu2aY#$*�bTu}q#Y?URMVM!dkJ|qjC;h^CgXI?U zm4nb9Cd$f0p!b2PmzZTpGP0>i!P~E|E`d&aq(=7|Oal}_G*1S-Y)j2Z-Jq>~ zFT_tBTBR_>pd{G<7h<`Q{P@Y7 zI!#E@H8Q=H0u?xEDxh=q6kKAnWP!;82O2!Z6&f;B$24BC*u#| zo!Q=&HE2SM!qufaJR;SpqhB^qHU*ENrjxHzqN1AmLYT0QVLQkNdD4{1{!i|W`{&*( zcvM;uK`?WRMi@tHD6M(d=xF@Dd#F#I;`T#qKNu%y@Q_!Bd=q1R=osh>XfaVCQzxvU zVYw0B$zc(Fnpv@SL-uM&TDK+1PUCPGkJOJ`C1qcFX@a~|CQ2=6y4bx`XoHGiIliei z<*iG}Al%JwhWtIS9(jLleB+;a~tez|+I^HCD;)rJXD?|>a@J3a`g zq?B!7U=gvj040Y7x{*CuyGDsHN4|R^*9=i6bR|E}MzX~_Dy-V#dg}I4C}ucplI~NP6r9=< zQp4BrQt$260%;0k93SLJZ_j~%5`FsvPv%2JwkT>(`h_Gi9$uPn5!{oppn)yT`{(N1 z>6nXFM=Q`ec?<0=%(BL#!nk`Lc2~Z^IuUP(YdYtCYC66cA}o)~vv%qFa*oFN@16#( z7|`3gbq!rzO0`JqSZAXM7}x#HIYsK|Lt!);A>}QA=DzB(d-cBBP@g}?e9)p5M&3R# zr~zDb*Ua(vL{x7w23Ap0wT-gJ6|wtPEGlUfh5c6MMk1#ykscT=tJtv~qP`VFafxGa+4FEVtsNy#_q)!^DAL0#jezv9iU$5ya(R#_t%YQr{|EvcH=NkF{^xFHo zi*9+Jn*x;i0`{%z12I+uCw^QE_oscnHlpuj-KUT%veMWNs3MMTWy#@BsJCUw^Gt4G zw?^2)MYor+hoc|JmR-GI;jq1|8~WG5ey`av%-f%xK7ls$vM;-*a*vpqCKUc0w%|w? z2IKbaTcJijvwF(2Fk}aB>(&hWBEV%EQ zdV831ZxS}!Qju1}d{5OLyZM>L5oWWeE31&sVosIG&) zD-p!S99J}d!%T#LG)VRp$r_P!3zt**|o zYLVj}-BQ+{S1^a>HXCWuF`1d+S!k~U{h0)=WDx$z_=5lA|J35Oa&|Ba7v5>46fmR` z7hphw_5dk)tkN=Ox%{vKGj=1cWq$J9A*iBRpe3119tXBkvtfU=^Gb)frd&$Y!?g0^ zQhg=or-XyWE{}H>p=)DeNvWaX4$z!Ktw~8sF8$r*K-b(24`gm`gj8srRg34mz@P>H z_C($P+iFz8>on4CTQEU~3I+=U8Sp72z@)Bk!1xoDEwMwYbX}!d=4k`S7u9Bah$=hq zyt*8u(Ohg&#Y~U9Wl3`r&{T3Z`#Hr!Qweev(9&LDDgJn0s>hxwde)kf+AafJ3U=oY zbyEf(cf}KP`yJ9MrY1O%11uqQs@p3Iq0h$Q@@#JvA@xQR()RBRgbXNO<^f zM=g%W-@)X?O6a@1cM3`Kh04oX@sHb~hCwgFY{Q=DRk5@^+T6UU6$_>}_9cYM-2=g_6#cO6jkP(*R4i9n(9u#?GWw&h?+4vnpEF5Kb=4q{q&k-r(Vu&yVwL# z=p?ar`>{JGPF`!;zF>aNS$IP0rSwLPP~|Y$H!Bt}MSl1mkC1;5elhf^H4LXkf?~rO zW_9ut>WpYOOARvb)?>i z(1h1f^uE&nv$^hb(h!*V*Dmn=cVPY7^GGv$2U=r$J2T7w)h}QhD+o70fFkme6I3tm zauPJ3OFj#X@XA6$i|~pOPrtZmuzzp5{b%g0rREW`;}wI=cAsN_7dKPP|hG8wi@J@w069{yNtSeTAonLU|S&Evyn=Z-4>Zny- zG~lFQtn2U?EdfT!zICKv^8V^}{P68&PsteeKW{Q@yJ;j22mrtn1^@u_-)_>v(%i!4 z?{N9w9wIEM$=YKvBJ?~^mt{+Puj(oggCZcbL=mY<$xD{%#JU@7d0eIPP73+^j!upy zRl$1Y=k^=Wejyg4sbJc9_ybTnRRDJql1FpVCR16URT zW^y!+b}k;!P%HR$SgMqnI`r^k7~15L46-0XQAdBuk26cPA{cKn_Bu4%}?I8?f_ z8pb%hcOE4j&fF@}52uE)e1L1e`sw2q1?tKu?L&QGG%iT2U~y`jas=v zigMvj9+lulS-AK)5z70Li{oHe=qxHw+hx#Q`|l)BLj!W_F8kf@3)m30_h$asw~a2Y zGODuExTU45-gQ<$4i$hA4J5-;+`8J0o_3GKPS@!lkWKq#=s@<;JM9|dy$L&eUp|MOs=T|D;!EBt#NvpKd^Kv!tK&%z=;5?Zq@iTHPU^=WoSZLCrGXlDOOrfQ_1E{#8D|R$K5p& zzD}1#N{kL}uN&qGy>!bYOhgsEMHc7@N|H7PpL4vfVjR7n@x)O(v9=tWy?)0L1x@w)M}Vl9s$om9WR9)TYKB~$I%9? zxIcO9eR@mlg%-#j7k5tt_v2n2YrexD%C$1W;RP*aaibsox(RO2Jq!>1JA=Br>4tb| zYs)*s8blbHPgvei;@s5MW%pS_#jX=HguVA`5Ip5xY`dj9oLZN&wXJ5WICEL`@~v{e z61X!3YhY`e_FYCbGT6%sh_m|diR=z?H=cgL*F=_c_cSPd&vJ}x5R#r!RTLh2mj4I!GE6{BYRgTJJbIlGr6ie z_6KY*etci3I$*!BXNRt?OxvBEG2WfPH^Tra9bW3uhs%s>8V{2zNWO2x*Dcf75SOp| z8HVxk$Kz9U{Z`%4S}}_5uI=2q+A{$=CssymugxN}-sqd)rB(gd^Ql{~aL#y}%@(x$ zB76%*MmU6VU}NFy-zygRw5(|V>|LBc0OJJl<$+YDRrsr;%#|w;hTA&qB}DPP{;n_5 zkbwy8eEC8kf$;18f!yBS-0ri_(h82;Q9}+3km7A76MBTbauG1dbZjjf!K!u1$@XxC z08RGZ3D9&4ix0ZLIcRh;ec-!6~{59RfsM?4iAU04nebpT|R9Y zZZH)5R9PUT-l*<4|I$hMUpr(5I6pg z;)Q>wg{i(q;v6*LjvF>%0o{2LM@9P(v2w}ZuVn@W6MGWS5{dGM3o%)=3Npg2JuG8c zsP|R+EVga=1|)af=*23;r+o1W2ygY;lWru}6;|L2%XNov4OlHoSm`4x~KD$^Pt?ajhcq_Xj*%Zw~1w?O$I zahD|>tLha?G_n)Pmb2fGYwW3}H(KJcD4YpwcZKI8g%ih9 z9h$mbpXu~>kHn7fQZHvOFf6a`>^nBC0|!34jN-NXk4BEWPMk$4z}~EeCs|BMaIJ5H zvmPE(#@yk1+Pn62byG&jp9-_`s*&?4Cq1+SZIo$$OW3`tl}%N~s$VD2cLeDZmPT+Q zA5mPP2yLEJ$|jP&2_lgV^SpFFG||D2{)TnmuxY&BSAL^g=4RZzt$}DSbgtGg%1qlO zBbVvyf3F`=#EN|aynPW-7wQ{!7F&E2gebmOp*4`ND1mbU2~EPeL$c7`_vpn-IYv!$&76Ed{wXYu?r@HB|DSo*yAYQ zV`KoGsVQ#Rg>ze}+}Nypyr*J+_+@u3@rTjeNi3oAYn;S;&lAdbU(n*e2n2pH^$4&QC z;-qX>KK@)VGk0b8tg}F=S>&?3ySXs;-~pZwq$ttbiSzUOv3oLlrIN2Tje{hG%Xv2h zYSCGV{?0Qg7?QF&lf=+7`}zJ}4f*8>Xm6?r4Qd}-6*^)Bvm@PwavSW}j`LC> z0&1_2u12Su#Irmf$egMV9W7ve-<(96=0LeA(mBcatF%t`mcRwP-IA6IJSE;ni?l&T zVh-x6i?Xi=%oaesg4dD~v{wuvaIq$sQz*6ygmhTPP##j7MwA%s6v?pEc$vyNOOKud zM0xI>pwBYtGo&>!&U#>uZj}}E0v4MY%X2tO+{)YBww{)eQLcneWmihbFbm94yiub2RJK

S>FXJP3zWVguptcvk<>P3t@Cw zR(^zC9x??U-ra-qDjk9~|Gd$IE!A)FXGtQKWvR7Mh5)O-R8*J162 z($_5mal_MAk>tF(L@9K^QfXSRM&Op-}$@Z$l+9^qUx?r8V4xJ{k@6Uhy6 zzb=40v-cb1pXK(s!pve^ngvCraaq5f@%gL97j!B;Fj2VhqyAc`6So;Vyo(TE#BTZtl?sza+ zc$|!<`HdQwn4&18h!?A_zCgJ-$m02QKhXbV*4*}WAv7oe04d`CBuMFv9UT6H9Zie6 zZTx~5!gq}SaDrdK5#61jD&!mjh$Xc}v`S>PN+i+0pv88f+e9z9slS7H5_(9NTtv-# zcD?N9ww>p>_VoJJ$yhIf-`q3<7B8j_ETG-4wDH!|f3w05n-7yG-+1@6$1u6=##Y6; z=%t7K9@`8q^{aU)v82!muM8bsvlWhP87%B}bVI++koxIdfU4TqCjZ#eVH{n;$r(p8 z#`9uJUt=i2p5<_Du_f1>@YU-bmZ!J#-A=+kuMb;yaiR~~+{(0}JtV(HpW<~GR7dBz zLJYWWHcgLSC{1^TOTa-@hcaHky0LkYH0@R(v=9!S?k{?-lt4_m`&=&=K?(v~7O-MX z#e($KR$~G5wCmv86PO2TzjDWlu0-qZ zEz@|h`dRnln98qeP75UeFRe=OFRcpb2cIkL%>x`TKrtm!xhhP3L-ahtK0%qoYkAvw z{<66r`jmhlm8@4r{jQVcrj;PKPZ=@Tr+JF-3v>`h`C{yv zZ%DXLg)r#f{qK*nb)k$|WQF7*(?T2f63XWMfadZf-EM9%jaK%X1e0YJ#k6srQ|%7| zp0}{WD|~Ve;ql`hrjqoNzQzZAavpxB%BFWiqztGhyx(9kC*Wyv*<_|DGjVtP*}wLN zpQ7D8^9Da&l7;cVlc)S4)#9G$?hfB{H4B(cHgZ(Dp8xU-HV!Uz%(<*2uBfna2q5R# zS3)0GY{*N`OC=g#xKJzSlXKd>my5uo{0{jy2xqaRZn{4n@g|8|Z*j&-GGO(EI`62r zxP$qRofWFJva58d7z3%x@9!i;)gSQ;=u5Tf^gU&58N(Ml z^|Or=$SvwkjvZcHB78kAb2(vVy6*)AK|d&onr;Kj^Ha1CYr(j-qy*NZ;k*&5gOpu7T*>mlj^z7N>cFiP7uFKzP4^%jekxL# z+ZhgS{#cKk1{a>i=` zs_q4YMwh3=0%t{}(GE_Z=kI=i6`Ff~*l<~&<8 zl?yePFxs(Te`J`+97bn*$GHrp*NpQT_it#3j^=vv|>A%_)< z1S$K-L`mg7(td+RQ?!swfmfcrmV7v%e8&oZoHELM1OAh+PAHZ4mxhT>Q2H=Ow~3vEPw#ZYjn)25wJxV3I1z+}+Z3a-V~sG(dk5p8?5 za)UGOma|BH)kqg$9EtBqx6_gE_;^&tSTFRKvh-r|WaY&FMcLu#Is0_}*!)<%>Bckm z1IIL77q%+cMK49{cabb$QnmGSiR!iE%U~>J zB~Y`v+xp#=lAt{b4<07RWUcOBlqIvd3Q|pOm}_A8+Yj_OYBBXTwY{fhbWF0;&KODz z8DNEd7ecnIB8`U{MuaA3@kg*GN@{BGf6+Kc=*cUWFd6=JA5q2~m~f1Pmp4%N!fDHY2bYCH#E6ke?KDrE9DBL@GTYHS$_zjeGcS`8#oPQ$ zXH@5dAa{K!8O*NAe}b&10k>AjacW9M#0^`eq1DEwL5CGbyhr284J@Tjf_I}C)FO>C z=Sd&2`XIsM#1VlX2iLWKXFNZ&LE_C7__rrG5dOH0s*Zs}T(0djkp+i!l+GfXSXo&S zu7Q&=?mx7Yjd>;{#R6?bSoM& z*yeZ&`3p1<#QA1yQtW8DDTFfUKI`8fW~)Le|BJGKY3Qa0jI71Jz(t%*m)m>XL$$-` z#blWkv8^1}%sV59Q(f$^ifNN? zw%L%xbp7KW57N63H@a^JW#s<4!Vy&%2ycKFy)iH<#bj*-alR<+c|- zB=!}>Wy_B}T_pqM+ie35ThAZitxaS2yj4e@6e`h8{N-;`g~27OlHC)KK{<0IwUfX9 zz}A{}wKw{Cl&cMrIYRHj#&hqTE=2$t6E;8A%}_r_$8z6>uT1O3uI7C^V#h`A*)D<~ z?E|cHM}qez2EDZVZAkY9qZ`)IY*wAw8R7eYHn7^+SRJ2&k1w`S_hjbUmAySTtfW)< z$%LW6#e)}<;bQZ0dHD9|X`I~2%pJdkF6uQcT4I|cH#YgN!aqH+fJAewHLGBQC~IBk z|1J|>YUsaTHF)qxXdJS;^1%d?YPDx(EpJu;Z8_N*V`ag?&rj9^bex8OcmV=DFCwT# zK%GOZs{pM~(-W#MV2%X9LIv@Mwz>ln1yTGh8I($jTZTo-Amk1$3M&Z&OP4YveO7WO za&muwffXrTVuYBW`r8#hl+9;$nMf+rJl;4JiMH}}$easuQ=*|dMmdPor5g!QMG1~p z2Zdrem0^2xBpj`M7O4lMpiYGlVQElpf`<06!7)@JXk=~Jai|K+(molcp&c#21mr@; ze+H@kUvM5f1)~OVfxdG&;EijYs1_?IdGaDn)0{+aB$CoxQEE8b=Md{q<)SWSx=Kev zNLFDNyiNv8P5cGp;*4$q{ci8__iH3krK!ZoIWXMLsSmwY5E@BF`4uQqZh~(Q{GO3TG1Q4#Q*2g zF@L*cd-Qkd;Klr(H|NgI|H0Ch+a8Xh_sUL5DY(IST;AQM!ZgS;AuK`zsJl4j#$d1fmAsm{Dked)fuv$pCY_}OQMtK$mg+tWk?8oRP|blb+5rmM5p47;*Vb!nS& zhf=M{ziwx%zT+l4xmWe%>$cG{2T~2-d3!)8*dEN9FX*;5lZIs}6%#Ivt0BM6&oF(4 zp3dsC-Q=c2l>1Wl72-LkC%q`SU=@3|CbjLfUzQx#+3Y~vE^v=oYkM3`>p7)MtF!#X zCZ(6TpSczu<~bPj1Vc{vIXG!nZFSD+3Lbi7+o}vU7}p}cC&j22cm&w3Ev_cewLq(k zM4viBDq%S7#V1{{MUUz^3z>cs2Z335tj$bq&hZq z0o=)-P}b034<}#a6eeO#@dgC+xx>k-PK|nO8+Hszn2Eu)20o5>D6e@aa?8LWu&iDC zOM?Mj?_mt&C~2gqk5v|}141}H%+a&W$dPS3qK8;I6Y#HHlt(rQ`D8PlO)F+9i#Fb2 z#EtQDnfm1jftz9}8x}y~&bTlIUg!$qP~fM+(^(Z7A1EYOZIyKBXYk0#s|6>%Yf5%m z7;@g-l4h>@ybbLkj!rBQ_ThaI9IWeJzL45Ll%HOZC1@o-C&~RWUVfa=*4b=atpZY} zF7y?Gn)J1qu7cvGb`bd&6zyl-&v-`x-x_V6)vD_Ay)t8I1z&*ZyLZR(b6}fUblP3g zZ0A0XxahlKpv>cA;b6_f`=I+if{m}Dhn}jc&Jh-ubg$X#s1&2}x(t4p+w))W6Vjxt zi;iE`{%nPa?s(+wR(Z79XJ^*X(*{q!G}#{gnYMCPzxOOk^0xO8j2KU(*sei+2IM4RnMax^p_T3W(xbX1xGL4V&OKWo} zW7SQ7X+BzGWDM*!efnj5_Ot^UD!6gS*z@_A?nhxUvzdglYZ(mdAEi!I1J58A{9>Qj zmNi2eP+ct<1g6;eYDfgFsVe8GLS>p8uIUA5lH@-NuHQ zIt>K6MP#^+Cc}_hOKdp$D|@Mgl~J~T-vXub|24FfAH|r)y<|?9_d&`ae*{G!q{^=G zcB&XaRsNzh4v)JyoM!ExX={|Z<_%g?!0YdJN6rwr9f<2Nm0<+7KXXsjsgKuii^T2! zY~)DlSmJQDG>Hxm2ldP5HsaUewEop?X{b<=>0n;FZ$%s{l&{8 zGg;Plg#k9`{1H`?e$AKErp-CHSN79stuQF8I>LZWz08WH@lc{U{b6Gl#}`v*?;}g^0-otpaKEvl9lm2kVc1 z8H)C&0jd=c&d)nfWJB~3HiKn>O>ms^M<=_xUb8b*@rf2jX8E5=H9gc)Tk%=To-=z{ znsv0h)TFlr4m%1dw5;Od)Vgfh!z~Arv|MUcS>z1Zaje%_$jXM*RpCTc7`O|cDLPs2 zwabPfN#V*T6tUlV&|0j5{|Ij=X^NC^jWxOHH|3i>H;q4J87N|OHk#p=Wgd^u-KS5e z;O^v+vcVg}FUqhjy74#Zyd;dSZRD{nXb^JF;)QRrBjzvWS>byL3?l;4O!6}V1M!Q! zA`sJp0GUdFx-YzZwg*NO&1s^5^PNB5(>VvHyx7B1K%B}$zqH|Bm<{a#u_34-TFwcz zjNY#FUWucQ^$o0n?>xVgP7rV&5^%N{e8Rc}7AR1^W41w}#^88|*=S;%!!uXmFa2F% zq1!=aoe+i(2$CwBjbpKRj8fms*Bj`BSbyKw8zkaQMV~}&a!6rXYxYMF!!iL{b+(z0 znO52h{-Uh#1uwNgxi!i;uyxwZ!(K2rjh|`nXOaX&%_(!_mu`Q^gJ;M@3G~?U9qDt` zz;t2Iupcx`|OkhF-av-j}QQDtYL>vM35e+_EC!+69LK>yI)@x%|9$3 z!;jDZBkdtPP}rLiRNh5xP~dps_j-cBTY-bn| zVHFqhE;JQuHH$asqkvx_6O{r>!aQ(gt}<2!B6YQJA>qe!HS~AQ;k+v$s47rnig9i$ ztvHk(QJ;EZSjJyI^E?<2#)Q0Eafv(W1uMHX`w>x=daq}NiKb9EhgGFj1sv@{>`CI0-AKJmVTsL`1$VQ|{(#p` z%Q+tv?ITDgOKv#uI2;CyTR53Q!aO1s*pgE7HG^=80(wqjhQ&$hRzzUMUPg1QoI6>y zQ{&l=X0*PvrVUU;;6qTAYF42^y(68hzW<)_JV7dc!&+@l%u1_R zGBuGb+pHp;1_wXc55h`#iLoG`^BM&{4pvLhSX7ZiL}zx0jd69nJF|nrxn(*|?pV!OVJD_jAN)AqgVEK>F5B$UkC&=B6> ze&P|qZ#7)2VSW6SMC*q3h<%V`@h5$58yk%LEMl_kvk6nUv(vPLvTtYEsv&6E2Dcm# z9t{=%Z07{Po5OewN+OzQxwM9STGQB+;3vKdugmYxL+{G5kcX^})g$f-JH345{RCto zh{KJ~-`bhF*c=!`_tce~iNB#Fp}0WH_4Z+p07>+Qta5|!YN&tyE1uB8rm={t2(`Z= z|21e|?qNz8Ry_2WX?#|Nc69Z{T9^7tdOy>WU3EJEAvy zmth$?c~C*aI}|9uyqaE#*aA3(Zo0|fPK8wsT57tMJ<;i}$J}+)FmXg^Hj2PW5?L)- zsktp~O_p$0laQw;Yr8H!%)md*Z&hbxUA!+Wp3LrQVFT=SsfY+2kq(fNx~xGjL_-3B z4UJrJY_sEi11T#OK(%<YlP-wo*BNXrFpC7Khz|&I=&TaC!RQSSAOz8 zZa9*k3d0*8gbry)Z6IGJC1yn?_{sUU5dZ5bjzUKQIKFxRQML9O+%RE>sqz9MayX^R z$`z~%RoY+LXtM8cY5zW`bd7T;RVxncFM)v$ATZ2rDf7G}vRtyESMOgC1GLe_b@?6C z&;1mKQE|0J!KzQJp_0(7rKS}FNC0g#0Uu3=h}kC<b zZNdH2Mx(D4ercmtpY^A>9HoD0qkN+ipPNv`-$8}nUc{sGWh<%YSRi{)+38A-nmXa) zRuRNe4utRU_ILKRNv8jl7c$^7ZFd58b!mhW_>u;0Z}Tvcy(C^njtvzr&M9WGX-dKG z%4kN&cS|^~ZnAOqzw`C6!M&93<+%l+q0d!i^=>+IZZQPSA&M*1_FW-_8Ef-Wr@)w2 zzd+VaEA_z}xyq~}d}+5XkbGdU(xVH@Ujz1%kLX+$KF=Pp@#juoCViS>gwv^X-5aw} zJW2K{Q=4~hPj>o(GQsR=IAei5!l{9S1}fbaH7tcql9e?tyj^Nq%xc0{6$M`|9sG6o zVgs`Ev(K>?>Su-fHYK{!0;MTLo=lv4>3vwKbYR|LXNV(WT`?5V4B@=@ObW!_5R6O# zup(*>WV9a-QsbEXCey{I6U+pXx#e&0nj>rM$9GP$IcVMTI(pRhG{%Nxo_A*lP8Uu`s>zJ)=N+0hjg=DB$)h6H8*B>%Wp&GPVoBjs9xnwL=XV}! zUud+zk+ndL9?V?3+5@p=Iq(y_{Dgj~(Qy#ea22px#}`E3Z__%qEUK7qJWO^xK%Fj-DA-3$>rY=!qO4P}{&7cbl%3}jyJQvAu{GxB;? zIECn<3zO6us(Oml@%b~L;NY!K6fFQ)eB)CQG;8|!VKt3AFOa4H?y!tTgm!-$s921M zQB=;u*dZ~O3vu199cpsua4kH|P1 zqO_c!q~tHQ4wJzhc0ms3b$DnN_HncH8-1{cu02nEjFe21JDc?Yh^6DS5}?I{^X&=# z8T4A*=O5)hD?zW9Gp4wV^AzLfr~|}OnX|-mnw4^)l<}G1_D7$@UKCmOoMNC6p(QsN z*~2QNsVt2<;~$vYtzQ=MZ5R}>t?e_I05txoC(|z)KU?;CENo-yvd-+0WnX?e@tl&o zD*fnO!7+DXy%V=sY2hcazV+no@ zx?|&NGhS`GO|75CcLMW1j^G#H2^7z;jgu8H(#BPmXAKrYl32PPS94oL9T#4!EM_!# zr=jA_d8M7>-RH(7NK4RY0Xrm})d?aNP%A0oN#*oVylLGzpORpkUxgag1jYhofp?4WM^AugO(wl-8IcZg?KPN!p|M|=D56j3-t0X*;;6N1 zK>9e4|Cvze9oj7DC*K-r?M=BR@&ah8_bSj!${c12Z*b5oDW^*MV4|i5u)!QC5B*bS z2PRo44k}g^Br*sZAb@klHUqEiP)n_0T#C{V33d{4YV8$E`0&7ExjXIfw(@dkw?u%v zE2aFO<$y1xi_qo`WJN#Vt-sKfaxB zED&mZ!XL^~-d94%$>lUp2+`vZ7Q-#tQQM%FN#B7(7^9sFe<=DhvyO7ac!k`P(>HqVBOesDs86Kk?8 z-b{q`kvUY)BjEL&=)FF3xoYq$TmZe|-oN*Xb|wygLtPXCtaQIl+n2C(NE&Q?Ey-YD z(eh>t5ZKdYc+fb5=Nftz=SGfq1-~9g2n4A=Yy%+jYSS&)x&hSkYC9XaTd@ z`guUBNZ2P59L{LvRG|ZC6(O6gd4qsZVr?`5ts)7aRa`^a>;SZi3+BXewcKrO`5kd`$L5@Rvwi(at0!oi+>>^9! zg`P$>3^fJxtDBe0Y-@jXkoDKK0FiA(iH*ysV<3CU)I^T`82P>Fi&XHzEsrP&by%P{ z%NmAInxjWbwvHZ$(P~fwvU-1&M`Cqgb6PL%6t0QfiujaZybuW(v5}~thjC3Ts23=} zjM54OWKv+7V|*fs{nL!%`qPYJe&I89&C~nSj1m{GONz>A9`oL0?X!M^6-Ts)StTf> zvK(pWx#Gu2>4Yiw>X6B62@VG?DEx8w;O$F3i(YFgUAZkYi1>rHDIONa-YM@nxi2H!UR6XyRJXID1&FfKULCr2)fvwUtSal{(DJs zvr;g557^<)snk!v!{7!deK!T(X4^S1x!Sisu11S>ph?rna*M(C1N)7IcFg$!^CQS~ zaeRbNG~4kMqcN=Qrx!XR^Ou@T?7N+HOH9=>u#j#=G4pQh?=nMeADU=fHe_1ll>_R+ zYZq}}+OTkSHSWzSiPsyI40`Ue8YeDR_Wa%X>V~)alQ9yk?C)GPV2i6&JTDV8x2+1l z!?EMP8Mu)7VY#|IJ34i4rMN_Q7fULGew}ahU76k zV!i0{_ z!67Bf9>V1vOLdz0+FdSv-@XdIr|F~DNy1%E#F-uXnIjRj{&0L_rdxZeD&a79Ms*N; zdO=gTnzP|3-`oM}1Kr#7*vE>tKFte$qg+x7FlhgK(1mJ!WRK_P$nL8&53F?_{;V?h z{D_e;sSt1uZ5&# z5e_1H+zd61Hk4G*69)p?+M81tKafhq8h16)wUN2&CU~Bn%ubHH)yFr z9d87=J!d`nI8K0UQJG2>QIAkmC8J?|k+84EIlSUBx(hwBi( zxm_W*bMSc074uhb37Hi#*=@;`(wIVC)ZHI5Z=zVA-O`W@$(DkGsr3h5 zLDiE(SdRe)yXN0OMp z_P-TmB{>6?L6lf=G4_MX`v(WXt!?^_Ro0aRSc~;INA) zd#k}n$&;snD_~BR0q7d5&;ebe{?D#)LNn1eZub$$2Ff*o)4D4ZzKl%7kby}Jr9d2D z4(@KMaTtS;2O?np*)=v!_O^voUdnL>))B&uhq+9!x7XlZ3ENL!lZE53lvtUr_3HCg zazqEz&ELWg>dap}Cy}Z*2QhJ3ytdfAESYax$FyT~Gsa80sjW8^Q#<)7PO^fVj6qZF znbph2mdmQTv@8+@kFD(mH_63dZpaE=#igEWPaC%=m22hks@lk5HH*xjHLwoe*4{bB zJ2@mtU94mJ8|;lb{yf+0Px?03FL6n=iV=hA?y}n-Unm0!)5-*YdhFtSvRkK$K&P@4 zugsq@x63}~>&~SB+#id!)El4iPCZ#*0qzf}Y+mf5wVxilsXC{Ws~_84^NA1kvo_b){hk-c)lU7fhBcgzK_Rz#%-YKyF=a2Z(rl@VI?r0kyFfls~k(vEUI8GTtBzO8!9KMAfww}RVpM_$W#O! zM0HLvCzES&y&Hbh3YI;J7HOZZ!9r3>>Uhew~29jn;>Iv#};bj z*sebVs|`^L<)>-5G@)5byAvz2Qz+oTi^!y~^=(6Tg?HHK#`8wYx^~goct$(m%OD8h zslKPBDWAhWu}{aQQWKtfzK>4Z*&m5duai$!ipGwXACIoCHhI|Y8#^q%f2(^zLuFi0 z@r7qH5@xKfSeXnARjLB1HG~iWxmR(~Q|`#ruwYlAWz-@gS)kR-5gUzdut3hE;~sIZn~SU*}D|!f3iI*10ghk8(Qo`cQxC!h5$-hF1K-9c^%f{<^_5 z*~5kd1vHpeF#l@FvvYScx3&3;3w?v?N)({Q{7FY1@mYZ^&fA262p*|u(rA)cD}gQ2 z0{Fx-7?$T}gMpM)g%H}@Zx zz)?}>6F8#CM)!>rAEk8(TWsts7|}9aKjeqyVi2Qjk2`mmk-NFyL+k44edx-`X1|au z7sGnkl_91rL-s>a0-l&3Ao6=pSCt*QT>S1QU6H~#H;2%@mzW%0yZe7*fxY3G4n}f{d#R|9P_P^ z|B2_CR^3(Megl}ESwqc$l7+m)HjcWz4eGJwWcBlR^v8*$Pu#a$q~=LCkdPg7E15#u z-V8U;dK8ATEGddgIV|*MoP4PvBSOUvZur$?a)}aAhXF=8`@j=cw(wd_Oj?>ntT;Lm zg^$i5UR5HpOS=(t$k7KD@NI5WpMU~N z03Rv-laCZfdI-VUf-{Sm7(v=EJp@aN+Kk8aS2-Sq^Y--+#CfjqV(Kj9NEcGK4(@8d zoS_UvO=HU~hS<;SHxxvlK731*uGG$Bun?~SO~H*!&aXjFMTDltrrK{cB!ik)Tw z5CM!bC6RSkD`p(_`6s3>0mBZQ>0=nD1PCjc^<6tJ!~^gOJP0Eqi{<6zKZs9ARbi!E z)L$B?qNYEHJ)`!rxz&{F3t6zInxF3t9PlgP_9( z@s=?H4vG_|gM-_Fy%<*(3QSa97e|asU#j>KxpU7_M-)o4LvIF?dRG25ne3sYo_$8L zY(b&(@>H1?W&`84s@;0JCm3`2qGLnM;Sc{16T`9h?o_|LSP5 zw#61jd|CaD>W>6QvXYEKsB*eT1r-Qk4o(8acVW`Oen-2$(s3qzg1p_u?6|M)a)eq! zlyq{kKFV`F%3SA3sb`}F>iY9=ad2Sd&j!-mdvC3l9It2FmC2jlULo>0WkuF6Yn#6+ zl&|(P-j82mUs@T30w=w{m0W)ixCnua4a)rR{p%O4#lQ|eC}i1)wd*`6I`=@7=H8Y8 zb*J_3p;SSJA{70J0I@^xVrg#w;^y185zOyA{_L8p(|||?mW871mgnihTOT{%g_)kR zscy^qhJ|B-e(QWtu%-y?LnL$A)HA0@){G&BnJp`5Y+USQB8e4H8*YHvSEXQO+`IxD z9FYCzhiq;H94@%a5{dwp5Yaf#4qxAIGN-i1yoG@yq&K9&Y7hEn_J7{`P=~v}(04Pb zo`-+~eVhEI5`Gocv~7Dv`CH9BRSx*`p4-eED~^v9LH7a8xv2zzWX@=t?0a4{2s%_)7f zOSsN*EB9soY=IKcV)J2PH-m=6=no(s$#*WlqW?le94Tyo=zm=Frt-KhOS3LK-}zxL zM?c_jIsSFH0K^WA3N^stauU&c?YmssKLMGjzw_4Fi4iE)15XkV{XhH_{qK}cb4m{{ zc6P zA0MlY^tCo3+PdC&c0GP@L`zK=$S>saB)MJZt@VJjv3`$!@TK0VHrYcf({{wLX}8$J zB=ZZkB>K{ajA~+;V(W^p0UR_CRVz{OVAe5<>(%@;Gg!}&*UlJ@r!I*F3py0x&!@3N z^Tlv_T~B9Erxr6HhlV35Jj1sZ@p*tdCb4i3-gnS=)=BWVE#0=6iK$(R7*R8(4v%M9 zGBR@9sbp??k&DA?El+%H8G_2cRT`;*6XDcta;TCS%K|L;xgXH{h|FYHo{CLVuK5B;G-e?!J^j`OCb{V@I2d#yY zS@Rc~BUdPaW z9Vg0Or>hl1;o0$O%~&^6G1L5tDt%l1xjE(-yLm>3~COVx3p3U6JMTl+`e~=yqDwvIV-c zSbAmph6&q5dF!YxJL{YBv(-e6MmLWg<#a7R#3Hl#^RR(Dx7{U4brC+xqHmLj?Yxd} zdttb!xkArf_i5NwWZzb3sMZfL85x+h_k7@%A25w}#rcv-Tf_e4Ukre=u;Lkgv$=;Cig$t1S1-QZe8iJNWfpnoqpfeV#UuncfuJXG3DhorcXR zuW3w#q=Si=^U6NP>%qy5+T?DZjJze&c|DVp4krFWHP=;4r2#u%w%X!d`9OSKMpAZ& zl~jd|DZ;6S7cq|RS&LW74I3blf+o0+p5!&6Bu7nOEYB^Nyj1%j!(0<)wPfiOb89lP z|1ue>q0}?;j_JN5bOw)(tGe_1>8$+m$<7;#9U?uG;>e)NqxkTdnd>ulK!lu@J)G+U zU)A-|oV!Z=t*+AtuJcCuZ&5VQ+r?+@$v=u)q9(@L)Ys0*cK5>GubMtllZt z9deatoPFT6eDcyXoIFW>e%kraVt7uk$M`g&*8cLNs(G2lwysvkUT3%bY5Syoh3`ZU zQ?=7Y%y4rg%_(CuVt#{{IcB3ejOn^)*H*XruK48e6UF}AQ0`?lM`JDZm=v2b8^1>r zuESQAt84Ux?maA+ats+rjxLc37z2LgUhvz@WD9HGhI6pR^d4Y&Kam-p&}QKa zAFq(xumUsb02f8$r+~R6XqVQBVGg_y5s_lf-YVi2ArvJ4;t_x;qya^&`MF>UDEW*) zDM>(J8M!SqxLJuXBJl;zBH~7OyS}P{j6_%8?u!V}!39={P=xTIh!_%1y#C0K%ylwgx8s`~P-o~(-DK{8c3d#@B+QLCV70!tgXayRj z5P48;P-3!E=wcZh0YGNk%M&{H>B3idT z{tbQh;N}$FWy5a~wP4|9GeQWa%83U$rGjemlu>#>(cwrGq)$qX&@(h-OspsXt%AYb zWg-Oij#}C&9wjAv643#5M<`|J={pCbN=Nv~u7FhDPnBnc4pHx*Snxi_*bE4HYIANX zyGRp)GH&G^QXuW65(GwqF7!c0)0IczAVh&_J3)mPSs0XX36kfNLi2$|n&*S=&TQAC zOAvt2n0CeqLj`~6FG2f6;2p3Y;gZ^1k}yXk$*LkApWo!^DV3hTjEsA4;i=?^is*mf zqDVZmoH>AH+Y z(_rH`hqf0N3P(jP6-Y-8{V15XE&1;IVg?xcZILxVY2)8L?#kts(kBzI3dx>&-??^2 z&bt7*RhoPDPS+bu%ut`l_r0VU7e>sK=J&a%L5Bz}==2F9ta?awxMIaMZH+Pkbem5Q8uy{3&J9M)o4{jBVS zsCZa=rF2%N<%m&|@r0b`8?>$}yudo1@+3xth=YW{HM9BcsE>QPIUYcY2^x9jvspqG zmI!QJu^@~fZBEuBIQcbd@YsUFfDiBDtq%sX`@~BjB18}_OAhUCVQy_jRAC_@WVeD6 zz+rNEKo^nj(c8a@7^sJ=5DMX1kSN&EUmpx%-R8oVTS(2;v!dN}zpn zPGRTVkiW^cZVx?7WxwMfeV1|lhF7yH+clq~U7eD^T;cX?&8;RDYNAK{WdZ#TXbWa> z{MtCA$`T4zpJnj~1O(L2eF|h&+u9N7uylf5IX5D0LIx<5MRjL)z9E93Olfs(t^{N0 z4hzA*S2R-&NgbL1i6EFvfrorkSv%j6tfy6CWW|T9cQYcOyLzaf^$nJ@YV{$8ecyDT z);Y`~+nIC*@GWTIbO@h~?|VYXlD;=9m)?~EN*nTu`i)H`kRUaDIp$E$d8>OOh&Kyx zVEN;dxCS!dC52^5v$8jjS!g;V62s8mZ`LrS)=2_orQ77hE{I_;OHo`*j9_txY*T@B zqPt=Jp6fwJ4;n)){lq00p}-^U-$dL>%-pjFMiJTN3qp^GK~rN$*?q}&Fv-9G&x`ix z1&m@X(yz<&v)ld@OsgRt!teCywqF>yPd2CJja0JV5nqZq_QL8oSP|xz-KiuYv`v-ib5k{3tx~o2u>L_$ymA7 z!pae4s=M&%^VGgEUx>SzAh@J#nhZ(o6q!G4qy*R*S`IJq-xG5L9a>jV(u>`CRV0#o zxpl~Fp)b)lEp+R?0VykN2{fRoWY5t_>yp^TgV6pokSjiCm_vSM4%ErF)KjA-UQtnsMuDz1N&W>0p5pbnUwP|25dxvd}!9)GR0;BK15a8WK z(A{(xk>{j9y(#-fppw#+#1Q-%tLzlzDogAl*%fLBp&u!zD~LZX-TK)!X&WzyjaV2n z2g;-*3%&*s#j3#C)7k|^Pc?;_WTkv_ki7ivD|@bynt1bCAoep4^{V1>9XX=-S7x=MW}ZM;d=IfZLEkEA%BF|8yy3{U!rl0N^&^x6}cB6nG>mr^`(Xs0+pIoVLoXB2OG*w?ik->@dt@f ze-!c~5r{28wNc4I1XM~bQW#VArLGVETJShzpuK|Igmkf2=$GPsRUgYp=Ja z{-+`^pjN$~7~tot9jbtW!~c7K>OTv*HC4aBJ03eKB zRsU_n;Gd2 z?BA7tJ#_Q;^0Xwc%l}~n=l>7l&tGli*I#XlKS2OS0s;#EaVzl8XXd}(@Ye$YfB)TO z|6KTgjR*YyeSrVsydG}%JI*2HA3wl9M&11#%IgVPzoS6Y{SoEA^RoU9;Pp70-vK(A z{tWQjaGSq_csqAztOh z{tn}H!sd63Ht|1V{GPY@JBZiGg5M#?r2h!b$Wk>c&)eo9m;E|<#!ZB<3FOj q5?=le<24ogJBG6PA2I$(%>Ek;I3RTPbL%%??>FEDP2v3WfBy%uREfd> literal 0 HcmV?d00001 diff --git a/docs/docs.gradle b/docs/docs.gradle index da30b78fd4..180fc891ea 100644 --- a/docs/docs.gradle +++ b/docs/docs.gradle @@ -2,7 +2,7 @@ apply plugin: 'base' task docs { - dependsOn 'manual:reference', 'faq:referenceHtmlSingle', 'apidocs', 'guides:asciidoctor' + dependsOn 'manual:asciidoctor', 'faq:referenceHtmlSingle', 'apidocs', 'guides:asciidoctor' } project('faq') { @@ -25,26 +25,37 @@ project('faq') { project('manual') { apply plugin: 'base' - apply plugin: 'docbook-reference' + apply plugin: 'asciidoctor' - [referenceHtmlMulti, referencePdf, referenceHtmlSingle]*.sourceDir = file('src/docbook') + ext.expandPlaceholders = "" + + asciidoctor { + backends = ["html5", "pdf"] + options = [ + eruby: 'erubis', + attributes: [ + copycss : '', + icons : 'font', + 'source-highlighter': 'prettify', + sectanchors : '', + toc2: '', + idprefix: '', + idseparator: '-', + doctype: 'book', + 'spring-security-version' : project.version, + revnumber : project.version + ] + ] + } - defaultTasks 'referenceHtmlMulti', 'referenceHtmlSingle', 'referencePdf' - def imagesDir = new File(projectDir, 'src/docbook/images'); ext.spec = copySpec { into ('reference') { - from("$buildDir/reference") + from("${asciidoctor.outputDir}/dist/") } } } -task reference (type: Copy) { - dependsOn 'manual:reference' - destinationDir = buildDir - with(project('manual').spec) -} - task apidocs(type: Javadoc) { destinationDir = new File(buildDir, 'apidocs') title = "Spring Security $version API" @@ -91,7 +102,7 @@ ext.apiSpec = copySpec { } } -assemble.dependsOn = [apidocs, 'manual:reference'] +assemble.dependsOn = [apidocs, 'manual:asciidoctor'] task docsZip(type: Zip) { dependsOn docs diff --git a/docs/guides/build.gradle b/docs/guides/build.gradle index 5a84b29b3b..d57a8ae180 100644 --- a/docs/guides/build.gradle +++ b/docs/guides/build.gradle @@ -1,20 +1,21 @@ + import org.asciidoctor.gradle.* file("src/asciidoc").eachFileMatch(~/.*\.asc/) { file-> task "asciidoctor-${file.name}"(type: AsciidoctorTask) { - outputDir = project.file("$buildDir/docs") - sourceDocumentName = file + sourceDocument = file options = [ + eruby: 'erubis', eruby: 'erubis', attributes: [ copycss : '', icons : 'font', 'source-highlighter': 'prettify', sectanchors : '', - 'toc-placement' : 'preamble', - toc: '', + toc2: '', idprefix: '', idseparator: '-', + doctype: 'book', 'spring-security-version' : project.version, revnumber : project.version ] @@ -30,6 +31,6 @@ task asciidoctor { ext.spec = copySpec { into ('guides') { - from("$buildDir/docs/") + from("$buildDir/asciidoctor/dist/html5/") } } \ No newline at end of file diff --git a/docs/manual/src/asciidoctor/Guardfile b/docs/manual/src/asciidoctor/Guardfile new file mode 100644 index 0000000000..955f2c6b4a --- /dev/null +++ b/docs/manual/src/asciidoctor/Guardfile @@ -0,0 +1,12 @@ +require 'asciidoctor' +require 'erb' + +guard 'shell' do + watch(/^.*\.adoc$/) {|m| + Asciidoctor.render_file(m[0], :to_dir => "build/", :safe => Asciidoctor::SafeMode::UNSAFE, :attributes=> {'idprefix' => '', 'idseparator' => '-', 'copycss' => '', 'icons' => 'font', 'source-highlighter' => 'prettify', 'sectanchors' => '', 'doctype' => 'book','toc2' => '', 'spring-security-version' => '3.2.0.CI-SNAPSHOT', 'revnumber' => '3.2.0.CI-SNAPSHOT' }) + } +end + +guard 'livereload' do + watch(%r{build/.+\.(css|js|html)$}) +end diff --git a/docs/manual/src/docbook/images/Authentication.gif b/docs/manual/src/asciidoctor/images/Authentication.gif similarity index 100% rename from docs/manual/src/docbook/images/Authentication.gif rename to docs/manual/src/asciidoctor/images/Authentication.gif diff --git a/docs/manual/src/docbook/images/access-decision-voting.graffle b/docs/manual/src/asciidoctor/images/access-decision-voting.graffle similarity index 100% rename from docs/manual/src/docbook/images/access-decision-voting.graffle rename to docs/manual/src/asciidoctor/images/access-decision-voting.graffle diff --git a/docs/manual/src/docbook/images/access-decision-voting.png b/docs/manual/src/asciidoctor/images/access-decision-voting.png similarity index 100% rename from docs/manual/src/docbook/images/access-decision-voting.png rename to docs/manual/src/asciidoctor/images/access-decision-voting.png diff --git a/docs/manual/src/docbook/images/after-invocation.graffle b/docs/manual/src/asciidoctor/images/after-invocation.graffle similarity index 100% rename from docs/manual/src/docbook/images/after-invocation.graffle rename to docs/manual/src/asciidoctor/images/after-invocation.graffle diff --git a/docs/manual/src/docbook/images/after-invocation.png b/docs/manual/src/asciidoctor/images/after-invocation.png similarity index 100% rename from docs/manual/src/docbook/images/after-invocation.png rename to docs/manual/src/asciidoctor/images/after-invocation.png diff --git a/docs/manual/src/docbook/images/note.png b/docs/manual/src/asciidoctor/images/note.png similarity index 100% rename from docs/manual/src/docbook/images/note.png rename to docs/manual/src/asciidoctor/images/note.png diff --git a/docs/manual/src/docbook/images/s2-banner-rhs.png b/docs/manual/src/asciidoctor/images/s2-banner-rhs.png similarity index 100% rename from docs/manual/src/docbook/images/s2-banner-rhs.png rename to docs/manual/src/asciidoctor/images/s2-banner-rhs.png diff --git a/docs/manual/src/docbook/images/s2_box_logo.png b/docs/manual/src/asciidoctor/images/s2_box_logo.png similarity index 100% rename from docs/manual/src/docbook/images/s2_box_logo.png rename to docs/manual/src/asciidoctor/images/s2_box_logo.png diff --git a/docs/manual/src/docbook/images/security-interception.graffle b/docs/manual/src/asciidoctor/images/security-interception.graffle similarity index 100% rename from docs/manual/src/docbook/images/security-interception.graffle rename to docs/manual/src/asciidoctor/images/security-interception.graffle diff --git a/docs/manual/src/docbook/images/security-interception.png b/docs/manual/src/asciidoctor/images/security-interception.png similarity index 100% rename from docs/manual/src/docbook/images/security-interception.png rename to docs/manual/src/asciidoctor/images/security-interception.png diff --git a/docs/manual/src/docbook/images/tip.png b/docs/manual/src/asciidoctor/images/tip.png similarity index 100% rename from docs/manual/src/docbook/images/tip.png rename to docs/manual/src/asciidoctor/images/tip.png diff --git a/docs/manual/src/asciidoctor/index.adoc b/docs/manual/src/asciidoctor/index.adoc new file mode 100644 index 0000000000..0d41c1adad --- /dev/null +++ b/docs/manual/src/asciidoctor/index.adoc @@ -0,0 +1,7579 @@ += Spring Security Reference +:author: Ben Alex, Luke Taylor, Rob Winch + +Spring Security is a powerful and highly customizable authentication and access-control framework. It is the de-facto standard for securing Spring-based applications. + +[[preface]] +== Preface +Spring Security provides a comprehensive security solution for J2EE-based enterprise software applications. As you will discover as you venture through this reference guide, we have tried to provide you a useful and highly configurable security system. + +Security is an ever-moving target, and it's important to pursue a comprehensive, system-wide approach. In security circles we encourage you to adopt "layers of security", so that each layer tries to be as secure as possible in its own right, with successive layers providing additional security. The "tighter" the security of each layer, the more robust and safe your application will be. At the bottom level you'll need to deal with issues such as transport security and system identification, in order to mitigate man-in-the-middle attacks. Next you'll generally utilise firewalls, perhaps with VPNs or IP security to ensure only authorised systems can attempt to connect. In corporate environments you may deploy a DMZ to separate public-facing servers from backend database and application servers. Your operating system will also play a critical part, addressing issues such as running processes as non-privileged users and maximising file system security. An operating system will usually also be configured with its own firewall. Hopefully somewhere along the way you'll be trying to prevent denial of service and brute force attacks against the system. An intrusion detection system will also be especially useful for monitoring and responding to attacks, with such systems able to take protective action such as blocking offending TCP/IP addresses in real-time. Moving to the higher layers, your Java Virtual Machine will hopefully be configured to minimize the permissions granted to different Java types, and then your application will add its own problem domain-specific security configuration. Spring Security makes this latter area - application security - much easier. + +Of course, you will need to properly address all security layers mentioned above, together with managerial factors that encompass every layer. A non-exhaustive list of such managerial factors would include security bulletin monitoring, patching, personnel vetting, audits, change control, engineering management systems, data backup, disaster recovery, performance benchmarking, load monitoring, centralised logging, incident response procedures etc. + +With Spring Security being focused on helping you with the enterprise application security layer, you will find that there are as many different requirements as there are business problem domains. A banking application has different needs from an ecommerce application. An ecommerce application has different needs from a corporate sales force automation tool. These custom requirements make application security interesting, challenging and rewarding. + +Please read <>, in its entirety to begin with. This will introduce you to the framework and the namespace-based configuration system with which you can get up and running quite quickly. To get more of an understanding of how Spring Security works, and some of the classes you might need to use, you should then read <>. The remaining parts of this guide are structured in a more traditional reference style, designed to be read on an as-required basis. We'd also recommend that you read up as much as possible on application security issues in general. Spring Security is not a panacea which will solve all security issues. It is important that the application is designed with security in mind from the start. Attempting to retrofit it is not a good idea. In particular, if you are building a web application, you should be aware of the many potential vulnerabilities such as cross-site scripting, request-forgery and session-hijacking which you should be taking into account from the start. The OWASP web site (http://www.owasp.org/) maintains a top ten list of web application vulnerabilities as well as a lot of useful reference information. + +We hope that you find this reference guide useful, and we welcome your feedback and <>. + +Finally, welcome to the Spring Security <>. + + +[[getting-started]] +== Getting Started +The later parts of this guide provide an in-depth discussion of the framework architecture and implementation classes, which you need to understand if you want to do any serious customization. In this part, we'll introduce Spring Security 3.0, give a brief overview of the project's history and take a slightly gentler look at how to get started using the framework. In particular, we'll look at namespace configuration which provides a much simpler way of securing your application compared to the traditional Spring bean approach where you have to wire up all the implementation classes individually. + +We'll also take a look at the sample applications that are available. It's worth trying to run these and experimenting with them a bit even before you read the later sections - you can dip back into them as your understanding of the framework increases. Please also check out the http://static.springsource.org/spring-security/site/index.html[project website] as it has useful information on building the project, plus links to articles, videos and tutorials. + + +[[introduction]] +=== Introduction + + +[[what-is-acegi-security]] +==== What is Spring Security? +Spring Security provides comprehensive security services for J2EE-based enterprise software applications. There is a particular emphasis on supporting projects built using The Spring Framework, which is the leading J2EE solution for enterprise software development. If you're not using Spring for developing enterprise applications, we warmly encourage you to take a closer look at it. Some familiarity with Spring - and in particular dependency injection principles - will help you get up to speed with Spring Security more easily. + +People use Spring Security for many reasons, but most are drawn to the project after finding the security features of J2EE's Servlet Specification or EJB Specification lack the depth required for typical enterprise application scenarios. Whilst mentioning these standards, it's important to recognise that they are not portable at a WAR or EAR level. Therefore, if you switch server environments, it is typically a lot of work to reconfigure your application's security in the new target environment. Using Spring Security overcomes these problems, and also brings you dozens of other useful, customisable security features. + +As you probably know two major areas of application security are "authentication" and "authorization" (or "access-control"). These are the two main areas that Spring Security targets. "Authentication" is the process of establishing a principal is who they claim to be (a "principal" generally means a user, device or some other system which can perform an action in your application)."Authorization" refers to the process of deciding whether a principal is allowed to perform an action within your application. To arrive at the point where an authorization decision is needed, the identity of the principal has already been established by the authentication process. These concepts are common, and not at all specific to Spring Security. + +At an authentication level, Spring Security supports a wide range of authentication models. Most of these authentication models are either provided by third parties, or are developed by relevant standards bodies such as the Internet Engineering Task Force. In addition, Spring Security provides its own set of authentication features. Specifically, Spring Security currently supports authentication integration with all of these technologies: + + +* HTTP BASIC authentication headers (an IETF RFC-based standard) + +* HTTP Digest authentication headers (an IETF RFC-based standard) + +* HTTP X.509 client certificate exchange (an IETF RFC-based standard) + +* LDAP (a very common approach to cross-platform authentication needs, especially in large environments) + +* Form-based authentication (for simple user interface needs) + +* OpenID authentication + +* Authentication based on pre-established request headers (such as Computer Associates Siteminder) + +* JA-SIG Central Authentication Service (otherwise known as CAS, which is a popular open source single sign-on system) + +* Transparent authentication context propagation for Remote Method Invocation (RMI) and HttpInvoker (a Spring remoting protocol) + +* Automatic "remember-me" authentication (so you can tick a box to avoid re-authentication for a predetermined period of time) + +* Anonymous authentication (allowing every unauthenticated call to automatically assume a particular security identity) + +* Run-as authentication (which is useful if one call should proceed with a different security identity) + +* Java Authentication and Authorization Service (JAAS) + +* JEE container autentication (so you can still use Container Managed Authentication if desired) + +* Kerberos + +* Java Open Source Single Sign On (JOSSO) * + +* OpenNMS Network Management Platform * + +* AppFuse * + +* AndroMDA * + +* Mule ESB * + +* Direct Web Request (DWR) * + +* Grails * + +* Tapestry * + +* JTrac * + +* Jasypt * + +* Roller * + +* Elastic Path * + +* Atlassian Crowd * + +* Your own authentication systems (see below) + + + +(* Denotes provided by a third party + +Many independent software vendors (ISVs) adopt Spring Security because of this significant choice of flexible authentication models. Doing so allows them to quickly integrate their solutions with whatever their end clients need, without undertaking a lot of engineering or requiring the client to change their environment. If none of the above authentication mechanisms suit your needs, Spring Security is an open platform and it is quite simple to write your own authentication mechanism. Many corporate users of Spring Security need to integrate with "legacy" systems that don't follow any particular security standards, and Spring Security is happy to "play nicely" with such systems. + +Irrespective of the authentication mechanism, Spring Security provides a deep set of authorization capabilities. There are three main areas of interest - authorizing web requests, authorizing whether methods can be invoked, and authorizing access to individual domain object instances. To help you understand the differences, consider the authorization capabilities found in the Servlet Specification web pattern security, EJB Container Managed Security and file system security respectively. Spring Security provides deep capabilities in all of these important areas, which we'll explore later in this reference guide. + + +[[history]] +==== History +Spring Security began in late 2003 as "The Acegi Security System for Spring". A question was posed on the Spring Developers' mailing list asking whether there had been any consideration given to a Spring-based security implementation. At the time the Spring community was relatively small (especially compared with the size today!), and indeed Spring itself had only existed as a SourceForge project from early 2003. The response to the question was that it was a worthwhile area, although a lack of time currently prevented its exploration. + +With that in mind, a simple security implementation was built and not released. A few weeks later another member of the Spring community inquired about security, and at the time this code was offered to them. Several other requests followed, and by January 2004 around twenty people were using the code. These pioneering users were joined by others who suggested a SourceForge project was in order, which was duly established in March 2004. + +In those early days, the project didn't have any of its own authentication modules. Container Managed Security was relied upon for the authentication process, with Acegi Security instead focusing on authorization. This was suitable at first, but as more and more users requested additional container support, the fundamental limitation of container-specific authentication realm interfaces became clear. There was also a related issue of adding new JARs to the container's classpath, which was a common source of end user confusion and misconfiguration. + +Acegi Security-specific authentication services were subsequently introduced. Around a year later, Acegi Security became an official Spring Framework subproject. The 1.0.0 final release was published in May 2006 - after more than two and a half years of active use in numerous production software projects and many hundreds of improvements and community contributions. + +Acegi Security became an official Spring Portfolio project towards the end of 2007 and was rebranded as "Spring Security". + +Today Spring Security enjoys a strong and active open source community. There are thousands of messages about Spring Security on the support forums. There is an active core of developers who work on the code itself and an active community which also regularly share patches and support their peers. + + +[[release-numbering]] +==== Release Numbering +It is useful to understand how Spring Security release numbers work, as it will help you identify the effort (or lack thereof) involved in migrating to future releases of the project. Each release uses a standard triplet of integers: MAJOR.MINOR.PATCH. The intent is that MAJOR versions are incompatible, large-scale upgrades of the API. MINOR versions should largely retain source and binary compatibility with older minor versions, thought there may be some design changes and incompatible udates. PATCH level should be perfectly compatible, forwards and backwards, with the possible exception of changes which are to fix bugs and defects. + +The extent to which you are affected by changes will depend on how tightly integrated your code is. If you are doing a lot of customization you are more likely to be affected than if you are using a simple namespace configuration. + +You should always test your application thoroughly before rolling out a new version. + + +[[get-spring-security]] +==== Getting Spring Security +You can get hold of Spring Security in several ways. You can download a packaged distribution from the main Spring http://www.springsource.com/download/community?project=Spring%20Security[download page], download individual jars (and sample WAR files) from the Maven Central repository (or a SpringSource Maven repository for snapshot and milestone releases) or, alternatively, you can build the project from source yourself. See the project web site for more details. + + +[[modules]] +===== Project Modules +In Spring Security 3.0, the codebase has been sub-divided into separate jars which more clearly separate different functionaltiy areas and third-party dependencies. If you are using Maven to build your project, then these are the modules you will add to your `pom.xml`. Even if you're not using Maven, we'd recommend that you consult the `pom.xml` files to get an idea of third-party dependencies and versions. Alternatively, a good idea is to examine the libraries that are included in the sample applications. + + +[[spring-security-core]] +====== Core - spring-security-core.jar +Contains core authentication and access-contol classes and interfaces, remoting support and basic provisioning APIs. Required by any application which uses Spring Security. Supports standalone applications, remote clients, method (service layer) security and JDBC user provisioning. Contains the top-level packages: + +* `org.springframework.security.core` + +* `org.springframework.security.access` + +* `org.springframework.security.authentication` + +* `org.springframework.security.provisioning` + + + + + +[[spring-security-remoting]] +====== Remoting - spring-security-remoting.jar +Provides intergration with Spring Remoting. You don't need this unless you are writing a remote client which uses Spring Remoting. The main package is `org.springframework.security.remoting`. + + +[[spring-security-web]] +====== Web - spring-security-web.jar +Contains filters and related web-security infrastructure code. Anything with a servlet API dependency. You'll need it if you require Spring Security web authentication services and URL-based access-control. The main package is `org.springframework.security.web`. + + +[[spring-security-config]] +====== Config - spring-security-config.jar +Contains the security namespace parsing code. You need it if you are using the Spring Security XML namespace for configuration. The main package is `org.springframework.security.config`. None of the classes are intended for direct use in an application. + + +[[spring-security-ldap]] +====== LDAP - spring-security-ldap.jar +LDAP authentication and provisioning code. Required if you need to use LDAP authentication or manage LDAP user entries. The top-level package is `org.springframework.security.ldap`. + + +[[spring-security-acl]] +====== ACL - spring-security-acl.jar +Specialized domain object ACL implementation. Used to apply security to specific domain object instances within your application. The top-level package is `org.springframework.security.acls`. + + +[[spring-security-cas]] +====== CAS - spring-security-cas.jar +Spring Security's CAS client integration. If you want to use Spring Security web authentication with a CAS single sign-on server. The top-level package is `org.springframework.security.cas`. + + +[[spring-security-openid]] +====== OpenID - spring-security-openid.jar +OpenID web authentication support. Used to authenticate users against an external OpenID server. `org.springframework.security.openid`. Requires OpenID4Java. + + +[[get-source]] +===== Checking out the Source +Since Spring Security is an Open Source project, we'd strongly encourage you to check out the source code using git. This will give you full access to all the sample applications and you can build the most up to date version of the project easily. Having the source for a project is also a huge help in debugging. Exception stack traces are no longer obscure black-box issues but you can get straight to the line that's causing the problem and work out what's happening. The source is the ultimate documentation for a project and often the simplest place to find out how something actually works. + +To obtain the source for the project, use the following git command: + +[source,txt] +---- +git clone https://github.com/spring-projects/spring-security.git +---- + +This will give you access to the entire project history (including all releases and branches) on your local machine. + + +[[new-3.1]] +=== What's new in Spring Security 3.1 +This section contains summary of the updates found in Spring Security 3.1. A detailed list of changes can be found in the project's https://jira.springsource.org/secure/IssueNavigator!executeAdvanced.jspa?jqlQuery=project+%3D+SEC+AND+fixVersion+in+%2812315%2C+11892%2C+11634%2C+11633%2C+11632%2C+11174%29+order+by+priority%2C+type&runQuery=true&clear=true[JIRA] + + +[[new-3.1-highlevel]] +==== High level updates found Spring Security 3.1 +Below you can find a high level summary of updates to Spring Security 3.1. + + +* Support for multiple http elements +* Support for stateless authentication +* DebugFilter provides additional debugging information +* Improved Active Directory LDAP support (i.e. ActiveDirectoryLdapAuthenticationProvider) +* Added Basic Crypto Module. +* The namespace is fully documented in the reference appendix. +* Added dependencies section to the reference appendix +* Support HttpOnly Flag for Cookies in Servlet 3.0 environments +* InMemoryUserDetailsManager provides in memory implementation of UserDetailsManager +* Support for hasPermission expression on the authorize JSP tag +* Support for disabling UI security (for testing purposes) +* Support erasing credentials after successful authentication +* Support clearing cookies on logout +* Spring Security Google App Engine example application +* Support for CAS proxy tickets +* Support for arbitrary implementations of JAAS Configuration +* Support nested switching of users for SwitchUserFilter + + + +[[new-3.1-ns]] +==== Spring Security 3.1 namespace updates +Below you can find a summary of updates to the Spring Security 3.1 namespace. + + +* Added support for multiple <>> elements and support for determining which one to use with <>, <>, and <>. Further information can be found in <> section of the reference. +* Added stateless option for <> +* Added support for <> and <>. +* Added <> +* Added <> and <> +* Added <>> +* Added Support for setting the AuthenticationDetailsSource using the namespace. See <>, <>, <>, and <>. +* Added support for http/expression-handler. This allows <>> to be used for web access expressions. +* Added <> +* Added <> +* Added <> +* Added <> +* Added <>> +* Added <> +* Added <> +* Added <>> +* Added <> +* Added <> +* Added <> and <> + + + +[[ns-config]] +=== Security Namespace Configuration + + +==== Introduction +Namespace configuration has been available since version 2.0 of the Spring framework. It allows you to supplement the traditional Spring beans application context syntax with elements from additional XML schema. You can find more information in the Spring http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/htmlsingle/spring-framework-reference.html[ Reference Documentation]. A namespace element can be used simply to allow a more concise way of configuring an individual bean or, more powerfully, to define an alternative configuration syntax which more closely matches the problem domain and hides the underlying complexity from the user. A simple element may conceal the fact that multiple beans and processing steps are being added to the application context. For example, adding the following element from the security namespace to an application context will start up an embedded LDAP server for testing use within the application: + +[source,xml] +---- + +---- + +This is much simpler than wiring up the equivalent Apache Directory Server + beans. The most common alternative configuration requirements are supported by + attributes on the `ldap-server` element and the user is isolated from worrying about which beans they need to create and what the bean property names are. footnote:[ +You can find out more about the use of the `ldap-server` element in the chapter on <>. +]. Use of a good XML editor while editing the application context file should provide information on the attributes and elements that are available. We would recommend that you try out the http://www.springsource.com/products/sts[SpringSource Tool Suite] as it has special features for working with standard Spring namespaces. + +To start using the security namespace in your application context, you need to have the `spring-security-config` jar on your classpath. Then all you need to do is add the schema declaration to your application context file: + +[source,xml] +---- + + ... + +---- + +In many of the examples you will see (and in the sample) applications, we + will often use "security" as the default namespace rather than "beans", which means we + can omit the prefix on all the security namespace elements, making the content easier to + read. You may also want to do this if you have your application context divided up into + separate files and have most of your security configuration in one of them. Your + security application context file would then start like this + +[source,xml] +---- + + ... + +---- + +We'll assume this syntax is being used from now on in this chapter. + + +===== Design of the Namespace +The namespace is designed to capture the most common uses of the framework and provide a simplified and concise syntax for enabling them within an application. The design is based around the large-scale dependencies within the framework, and can be divided up into the following areas: + +* __Web/HTTP Security__ - the most complex part. Sets up the filters and related service beans used to apply the framework authentication mechanisms, to secure URLs, render login and error pages and much more. + +* __Business Object (Method) Security__ - options for securing the service layer. + +* __AuthenticationManager__ - handles authentication requests from other parts of the framework. + +* __AccessDecisionManager__ - provides access decisions for web and method security. A default one will be registered, but you can also choose to use a custom one, declared using normal Spring bean syntax. + +* __AuthenticationProvider__s - mechanisms against which the authentication manager authenticates users. The namespace provides supports for several standard options and also a means of adding custom beans declared using a traditional syntax. + +* __UserDetailsService__ - closely related to authentication providers, but often also required by other beans. + +We'll see how to configure these in the following sections. + +[[ns-getting-started]] +==== Getting Started with Security Namespace Configuration +In this section, we'll look at how you can build up a namespace configuration to use some of the main features of the framework. Let's assume you initially want to get up and running as quickly as possible and add authentication support and access control to an existing web application, with a few test logins. Then we'll look at how to change over to authenticating against a database or other security repository. In later sections we'll introduce more advanced namespace configuration options. + +[[ns-web-xml]] +===== web.xml Configuration +The first thing you need to do is add the following filter declaration to your `web.xml` file: + +[source,xml] +---- + + springSecurityFilterChain + org.springframework.web.filter.DelegatingFilterProxy + + + + springSecurityFilterChain + /* + +---- + +This provides a hook into the Spring Security web + infrastructure. `DelegatingFilterProxy` is a Spring Framework class which delegates to a filter implementation which is defined as a Spring bean in your application context. In this case, the bean is named "springSecurityFilterChain", which is an internal infrastructure bean created by the namespace to handle web security. Note that you should not use this bean name yourself. Once you've added this to your `web.xml`, you're ready to start editing your application context file. Web security services are configured using the `` element. + + +[[ns-minimal]] +===== A Minimal Configuration +All you need to enable web security to begin with is + +[source,xml] +---- + + + + + +---- + +Which says that we want all URLs within our application to be secured, + requiring the role `ROLE_USER` to access them, we want to log in to the application using a form with username and password, and that we want a logout URL registered which will allow us to log out of the application. `` element is the parent for all web-related namespace functionality. The `` element defines a `pattern` which is matched against the URLs of incoming requests using an ant path style syntax footnote:[See the section on <> in the Web Application Infrastructure chapter for more details on how matches are actually performed.]. You can also use regular-expression matching as an alternative (see the namespace appendix for more details). The `access` attribute defines the access requirements for requests matching the given pattern. With the default configuration, this is typically a comma-separated list of roles, one of which a user must have to be allowed to make the request. The prefix"ROLE_" is a marker which indicates that a simple comparison with the user's authorities should be made. In other words, a normal role-based check should be used. Access-control in Spring Security is not limited to the use of simple roles (hence the use of the prefix to differentiate between different types of security attributes). We'll see later how the interpretation can vary footnote:[The interpretation of the comma-separated values in the `access` attribute depends on the implementation of the <> which is used. In Spring Security 3.0, the attribute can also be populated with an <>.]. + +[NOTE] +==== + +You can use multiple `` elements to define different access requirements for different sets of URLs, but they will be evaluated in the order listed and the first match will be used. So you must put the most specific matches at the top. You can also add a `method` attribute to limit the match to a particular HTTP method (`GET`, `POST`, `PUT` etc.). + +==== + +To add some users, you can define a set of test data directly in the namespace: + +[source,xml] +---- + + + + + + + + +---- + +[subs="quotes"] +**** +If you are familiar with pre-namespace versions of the framework, you can probably already guess roughly what's going on here. The `` element is responsible for creating a `FilterChainProxy` and the filter beans which it uses. Common problems like incorrect filter ordering are no longer an issue as the filter positions are predefined. + +The `` element creates a `DaoAuthenticationProvider` bean and the `` element creates an `InMemoryDaoImpl`. All `authentication-provider` elements must be children of the `` element, which creates a `ProviderManager` and registers the authentication providers with it. You can find more detailed information on the beans that are created in the <>. It's worth cross-checking this if you want to start understanding what the important classes in the framework are and how they are used, particularly if you want to customise things later. +**** + +The configuration above defines two users, their passwords and their roles within the application (which will be used for access control). It is also possible to load user information from a standard properties file using the `properties` attribute on `user-service`. See the section on <> for more details on the file format. Using the `` element means that the user information will be used by the authentication manager to process authentication requests. You can have multiple `` elements to define different authentication sources and each will be consulted in turn. + +At this point you should be able to start up your application and you will be required to log in to proceed. Try it out, or try experimenting with the"tutorial" sample application that comes with the project. + + +[[ns-form-and-basic]] +===== Form and Basic Login Options +You might be wondering where the login form came from when you were prompted to log in, since we made no mention of any HTML files or JSPs. In fact, since we didn't explicitly set a URL for the login page, Spring Security generates one automatically, based on the features that are enabled and using standard values for the URL which processes the submitted login, the default target URL the user will be sent to after logging in and so on. However, the namespace offers plenty of support to allow you to customize these options. For example, if you want to supply your own login page, you could use: + +[source,xml] +---- + + + + + +---- + +Also note that we've added an extra `intercept-url` element to say that any requests for the login page should be available to anonymous users footnote:[See the chapter on <> and also the <> class for more details on how the value `IS_AUTHENTICATED_ANONYMOUSLY` is processed.]. Otherwise the request would be matched by the pattern `/**` and it wouldn't be possible to access the login page itself! This is a common configuration error and will result in an infinite loop in the application. Spring Security will emit a warning in the log if your login page appears to be secured. It is also possible to have all requests matching a particular pattern bypass the security filter chain completely, by defining a separate `http` element for the pattern like this: + +[source,xml] +---- + + + + + + + +---- + +From Spring Security 3.1 it is now possible to use multiple `http` elements to define separate security filter chain configurations for different request patterns. If the `pattern` attribute is omitted from an `http` element, it matches all requests. Creating an unsecured pattern is a simple example of this syntax, where the pattern is mapped to an empty filter chain footnote:[The use of multiple `` elements is an important feature, allowing the namespace to simultaneously support both stateful and stateless paths within the same application, for example. The previous syntax, using the attribute `filters="none"` on an `intercept-url` element is incompatible with this change and is no longer supported in 3.1. +]. We'll look at this new syntax in more detail in the chapter on the <>. + +It's important to realise that these unsecured requests will be completely oblivious to any Spring Security web-related configuration or additional attributes such as `requires-channel`, so you will not be able to access information on the current user or call secured methods during the request. Use `access='IS_AUTHENTICATED_ANONYMOUSLY'` as an alternative if you still want the security filter chain to be applied. + +If you want to use basic authentication instead of form login, then change the configuration to + +[source,xml] +---- + + + + +---- + +Basic authentication will then take precedence and will be used to prompt for a login when a user attempts to access a protected resource. Form login is still available in this configuration if you wish to use it, for example through a login form embedded in another web page. + +[[ns-form-target]] +====== Setting a Default Post-Login Destination +If a form login isn't prompted by an attempt to access a protected resource, the `default-target-url` option comes into play. This is the URL the user will be taken to after successfully logging in, and defaults to "/". You can also configure things so that the user __always__ ends up at this page (regardless of whether the login was "on-demand" or they explicitly chose to log in) by setting the `always-use-default-target` attribute to "true". This is useful if your application always requires that the user starts at a "home" page, for example: + +[source,xml] +---- + + + + + +---- + +For even more control over the destination, you can use the `authentication-success-handler-ref` attribute as an alternative to `default-target-url`. The referenced bean should be an instance of `AuthenticationSuccessHandler`. You'll find more on this in the <> chapter and also in the namespace appendix, as well as information on how to customize the flow when authentication fails. + +[[ns-logout]] +===== Logout Handling +The `logout` element adds support for logging out by navigating to a particular URL. The default logout URL is `/j_spring_security_logout`, but you can set it to something else using the `logout-url` attribute. More information on other available attributes may be found in the namespace appendix. + +[[ns-auth-providers]] +===== Using other Authentication Providers +In practice you will need a more scalable source of user information than a few names added to the application context file. Most likely you will want to store your user information in something like a database or an LDAP server. LDAP namespace configuration is dealt with in the <>, so we won't cover it here. If you have a custom implementation of Spring Security's `UserDetailsService`, called "myUserDetailsService" in your application context, then you can authenticate against this using + +[source,xml] +---- + + + + + +---- + +If you want to use a database, then you can use + +[source,xml] +---- + + + + + +---- + +Where "securityDataSource" is the name of a `DataSource` bean in the application context, pointing at a database containing the standard Spring Security <>. Alternatively, you could configure a Spring Security `JdbcDaoImpl` bean and point at that using the `user-service-ref` attribute: + +[source,xml] +---- + + + + + + + +---- + +You can also use standard `AuthenticationProvider` beans as follows + +[source,xml] +---- + + + + + +---- + +where `myAuthenticationProvider` is the name of a bean in your application context which implements `AuthenticationProvider`. You can use multiple `authentication-provider` elements, in which case the providers will be queried in the order they are declared. See <> for more on information on how the Spring Security `AuthenticationManager` is configured using the namespace. + +[[ns-password-encoder]] +====== Adding a Password Encoder +Passwords should always be encoded using a secure hashing algorithm designed for the purpose (not a standard algorithm like SHA or MD5). This is supported by the `` element. With bcrypt encoded passwords, the original authentication provider configuration would look like this: + +[source,xml] +---- + + + + + + + + + + + + +---- + + + +Bcrypt is a good choice for most cases, unless you have a legacy system which forces you to use a different algorithm. If you are using a simple hashing algorithm or, even worse, storing plain text passwords, then you should consider migrating to a more secure option like bcrypt. + +[[ns-web-advanced]] +==== Advanced Web Features + +[[ns-remember-me]] +===== Remember-Me Authentication +See the separate <> for information on remember-me namespace configuration. + +[[ns-requires-channel]] +===== Adding HTTP/HTTPS Channel Security +If your application supports both HTTP and HTTPS, and you require that particular URLs can only be accessed over HTTPS, then this is directly supported using the `requires-channel` attribute on ``: + +[source,xml] +---- + + + + ... + +---- + +With this configuration in place, if a user attempts to access anything matching the "/secure/**" pattern using HTTP, they will first be redirected to an HTTPS URL footnote:[For more details on how channel-processing is implemented, see the Javadoc for `ChannelProcessingFilter` and related classes.]. The available options are "http", "https" or "any". Using the value "any" means that either HTTP or HTTPS can be used. + +If your application uses non-standard ports for HTTP and/or HTTPS, you can specify a list of port mappings as follows: + +[source,xml] +---- + + ... + + + + +---- + +Note that in order to be truly secure, an application should not use HTTP at all or switch between HTTP and HTTPS. It should start in HTTPS (with the user entering an HTTPS URL) and use a secure connection throughout to avoid any possibility of man-in-the-middle attacks. + +[[ns-session-mgmt]] +===== Session Management + +====== Detecting Timeouts +You can configure Spring Security to detect the submission of an invalid session ID and redirect the user to an appropriate URL. This is achieved through the `session-management` element: + +[source,xml] +---- + + ... + + +---- + +Note that if you use this mechanism to detect session timeouts, it may falsely report an error if the user logs out and then logs back in without closing the browser. This is because the session cookie is not cleared when you invalidate the session and will be resubmitted even if the user has logged out. You may be able to explicitly delete the JSESSIONID cookie on logging out, for example by using the following syntax in the logout handler: + +[source,xml] +---- + + + +---- + +Unfortunately this can't be guaranteed to work with every servlet container, so you will need to test it in your environment + +[NOTE] +==== +If you are running your application behind a proxy, you may also be able to remove the session cookie by configuring the proxy server. For example, using Apache HTTPD's mod_headers, the following directive would delete the `JSESSIONID` cookie by expiring it in the response to a logout request (assuming the application is deployed under the path `/tutorial`): + +[source,xml] +---- + + Header always set Set-Cookie "JSESSIONID=;Path=/tutorial;Expires=Thu, 01 Jan 1970 00:00:00 GMT" + +---- +==== + + +[[ns-concurrent-sessions]] +====== Concurrent Session Control +If you wish to place constraints on a single user's ability to log in to your application, Spring Security supports this out of the box with the following simple additions. First you need to add the following listener to your `web.xml` file to keep Spring Security updated about session lifecycle events: + +[source,xml] +---- + + + org.springframework.security.web.session.HttpSessionEventPublisher + + +---- + +Then add the following lines to your application context: + +[source,xml] +---- + + ... + + + + +---- + +This will prevent a user from logging in multiple times - a second login will cause the first to be invalidated. Often you would prefer to prevent a second login, in which case you can use + +[source,xml] +---- + + ... + + + + +---- + +The second login will then be rejected. By "rejected", we mean that the user will be sent to the `authentication-failure-url` if form-based login is being used. If the second authentication takes place through another non-interactive mechanism, such as "remember-me", an "unauthorized" (401) error will be sent to the client. If instead you want to use an error page, you can add the attribute `session-authentication-error-url` to the `session-management` element. + +If you are using a customized authentication filter for form-based login, then you have to configure concurrent session control support explicitly. More details can be found in the <>. + +[[ns-session-fixation]] +====== Session Fixation Attack Protection +http://en.wikipedia.org/wiki/Session_fixation[Session fixation] attacks are a potential risk where it is possible for a malicious attacker to create a session by accessing a site, then persuade another user to log in with the same session (by sending them a link containing the session identifier as a parameter, for example). Spring Security protects against this automatically by creating a new session or otherwise changing the session ID when a user logs in. If you don't require this protection, or it conflicts with some other requirement, you can control the behavior using the `session-fixation-protection` attribute on ``, which has four options + +* `none` - Don't do anything. The original session will be retained. + +* `newSession` - Create a new "clean" session, without copying the existing session data (Spring Security-related attributes will still be copied). + +* `migrateSession` - Create a new session and copy all existing session attributes to the new session. This is the default in Servlet 3.0 or older containers. + +* `changeSessionId` - Do not create a new session. Instead, use the session fixation protection provided by the Servlet container (`HttpServletRequest#changeSessionId()`). This option is only available in Servlet 3.1 (Java EE 7) and newer containers. Specifying it in older containers will result in an exception. This is the default in Servlet 3.1 and newer containers. + + +When session fixation protection occurs, it results in a `SessionFixationProtectionEvent` being published in the application context. If you use `changeSessionId`, this protection will __also__ result in any `javax.servlet.http.HttpSessionIdListener` s being notified, so use caution if your code listens for both events. See the <> chapter for additional information. + + +[[ns-openid]] +===== OpenID Support +The namespace supports http://openid.net/[OpenID] login either instead of, or in addition to normal form-based login, with a simple change: + +[source,xml] +---- + + + + +---- + +You should then register yourself with an OpenID provider (such as myopenid.com), and add the user information to your in-memory `` : + +[source,xml] +---- + +---- + +You should be able to login using the `myopenid.com` site to authenticate. It is also possible to select a specific `UserDetailsService` bean for use OpenID by setting the `user-service-ref` attribute on the `openid-login` element. See the previous section on <> for more information. Note that we have omitted the password attribute from the above user configuration, since this set of user data is only being used to load the authorities for the user. A random password will be generate internally, preventing you from accidentally using this user data as an authentication source elsewhere in your configuration. + + +====== Attribute Exchange +Support for OpenID http://openid.net/specs/openid-attribute-exchange-1_0.html[attribute exchange]. As an example, the following configuration would attempt to retrieve the email and full name from the OpenID provider, for use by the application: + +[source,xml] +---- + + + + + + +---- + +The "type" of each OpenID attribute is a URI, determined by a particular schema, in this case http://axschema.org/[http://axschema.org/]. If an attribute must be retrieved for successful authentication, the `required` attribute can be set. The exact schema and attributes supported will depend on your OpenID provider. The attribute values are returned as part of the authentication process and can be accessed afterwards using the following code: + +[source,java] +---- +OpenIDAuthenticationToken token = + (OpenIDAuthenticationToken)SecurityContextHolder.getContext().getAuthentication(); +List attributes = token.getAttributes(); +---- + +The `OpenIDAttribute` contains the attribute type and the retrieved value (or values in the case of multi-valued attributes). We'll see more about how the `SecurityContextHolder` class is used when we look at core Spring Security components in the <> chapter. Multiple attribute exchange configurations are also be supported, if you wish to use multiple identity providers. You can supply multiple `attribute-exchange` elements, using an `identifier-matcher` attribute on each. This contains a regular expression which will be matched against the OpenID identifier supplied by the user. See the OpenID sample application in the codebase for an example configuration, providing different attribute lists for the Google, Yahoo and MyOpenID providers. + + +[[ns-headers]] +===== Response Headers +For additional information on how to customize the headers element refer to the <> section of the reference. + + +[[ns-custom-filters]] +===== Adding in Your Own Filters +If you've used Spring Security before, you'll know that the framework maintains a chain of filters in order to apply its services. You may want to add your own filters to the stack at particular locations or use a Spring Security filter for which there isn't currently a namespace configuration option (CAS, for example). Or you might want to use a customized version of a standard namespace filter, such as the `UsernamePasswordAuthenticationFilter` which is created by the `` element, taking advantage of some of the extra configuration options which are available by using the bean explicitly. How can you do this with namespace configuration, since the filter chain is not directly exposed? + +The order of the filters is always strictly enforced when using the namespace. When the application context is being created, the filter beans are sorted by the namespace handling code and the standard Spring Security filters each have an alias in the namespace and a well-known position. + +[NOTE] +==== +In previous versions, the sorting took place after the filter instances had been created, during post-processing of the application context. In version 3.0+ the sorting is now done at the bean metadata level, before the classes have been instantiated. This has implications for how you add your own filters to the stack as the entire filter list must be known during the parsing of the `` element, so the syntax has changed slightly in 3.0. +==== + +The filters, aliases and namespace elements/attributes which create the filters are shown in <>. The filters are listed in the order in which they occur in the filter chain. + +[[filter-stack]] +.Standard Filter Aliases and Ordering +|=== +| Alias | Filter Class | Namespace Element or Attribute + +| CHANNEL_FILTER +| `ChannelProcessingFilter` +| `http/intercept-url@requires-channel` + +| SECURITY_CONTEXT_FILTER +| `SecurityContextPersistenceFilter` +| `http` + +| CONCURRENT_SESSION_FILTER +| `ConcurrentSessionFilter` +| `session-management/concurrency-control` + +| HEADERS_FILTER +| `HeaderWriterFilter` +| `http/headers` + +| CSRF_FILTER +| `CsrfFilter` +| `http/csrf` + +| LOGOUT_FILTER +| `LogoutFilter` +| `http/logout` + +| X509_FILTER +| `X509AuthenticationFilter` +| `http/x509` + +| PRE_AUTH_FILTER +| `AstractPreAuthenticatedProcessingFilter` Subclasses +| N/A + +| CAS_FILTER +| `CasAuthenticationFilter` +| N/A + +| FORM_LOGIN_FILTER +| `UsernamePasswordAuthenticationFilter` +| `http/form-login` + +| BASIC_AUTH_FILTER +| `BasicAuthenticationFilter` +| `http/http-basic` + +| SERVLET_API_SUPPORT_FILTER +| `SecurityContextHolderAwareRequestFilter` +| `http/@servlet-api-provision` + +| JAAS_API_SUPPORT_FILTER +| `JaasApiIntegrationFilter` +| `http/@jaas-api-provision` + +| REMEMBER_ME_FILTER +| `RememberMeAuthenticationFilter` +| `http/remember-me` + +| ANONYMOUS_FILTER +| `AnonymousAuthenticationFilter` +| `http/anonymous` + +| SESSION_MANAGEMENT_FILTER +| `SessionManagementFilter` +| `session-management` + +| EXCEPTION_TRANSLATION_FILTER +| `ExceptionTranslationFilter` +| `http` + +| FILTER_SECURITY_INTERCEPTOR +| `FilterSecurityInterceptor` +| `http` + +| SWITCH_USER_FILTER +| `SwitchUserFilter` +| N/A +|=== + +You can add your own filter to the stack, using the `custom-filter` element and one of these names to specify the position your filter should appear at: + +[source,xml] +---- + + + + + +---- + +You can also use the `after` or `before` attributes if you want your filter to be inserted before or after another filter in the stack. The names "FIRST" and "LAST" can be used with the `position` attribute to indicate that you want your filter to appear before or after the entire stack, respectively. + +.Standard Filter Aliases and OrderingAvoiding filter position conflicts +[TIP] +==== + +If you are inserting a custom filter which may occupy the same position as one of the standard filters created by the namespace then it's important that you don't include the namespace versions by mistake. Remove any elements which create filters whose functionality you want to replace. + +Note that you can't replace filters which are created by the use of the `` element itself - `SecurityContextPersistenceFilter`, `ExceptionTranslationFilter` or `FilterSecurityInterceptor`. Some other filters are added by default, but you can disable them. An `AnonymousAuthenticationFilter` is added by default and unless you have <> disabled, a `SessionManagementFilter` will also be added to the filter chain. + +==== + +If you're replacing a namespace filter which requires an authentication entry point (i.e. where the authentication process is triggered by an attempt by an unauthenticated user to access to a secured resource), you will need to add a custom entry point bean too. + + +[[ns-entry-point-ref]] +====== Setting a Custom +`AuthenticationEntryPoint` +If you aren't using form login, OpenID or basic authentication through the namespace, you may want to define an authentication filter and entry point using a traditional bean syntax and link them into the namespace, as we've just seen. The corresponding `AuthenticationEntryPoint` can be set using the `entry-point-ref` attribute on the `` element. + +The CAS sample application is a good example of the use of custom beans with the namespace, including this syntax. If you aren't familiar with authentication entry points, they are discussed in the <> chapter. + + +[[ns-method-security]] +==== Method Security +From version 2.0 onwards Spring Security has improved support substantially for adding security to your service layer methods. It provides support for JSR-250 annotation security as well as the framework's original `@Secured` annotation. From 3.0 you can also make use of new <>. You can apply security to a single bean, using the `intercept-methods` element to decorate the bean declaration, or you can secure multiple beans across the entire service layer using the AspectJ style pointcuts. + + +[[ns-global-method]] +===== The Element +This element is used to enable annotation-based security in your application (by setting the appropriate attributes on the element), and also to group together security pointcut declarations which will be applied across your entire application context. You should only declare one `` element. The following declaration would enable support for Spring Security's `@Secured`: + +[source,xml] +---- + +---- + +Adding an annotation to a method (on an class or interface) would then limit the access to that method accordingly. Spring Security's native annotation support defines a set of attributes for the method. These will be passed to the `AccessDecisionManager` for it to make the actual decision: + +[source,java] +---- +public interface BankService { + + @Secured("IS_AUTHENTICATED_ANONYMOUSLY") + public Account readAccount(Long id); + + @Secured("IS_AUTHENTICATED_ANONYMOUSLY") + public Account[] findAccounts(); + + @Secured("ROLE_TELLER") + public Account post(Account account, double amount); +} +---- + +Support for JSR-250 annotations can be enabled using + +[source,xml] +---- + +---- + +These are standards-based and allow simple role-based constraints to be applied but do not have the power Spring Security's native annotations. To use the new expression-based syntax, you would use + +[source,xml] +---- + +---- + +and the equivalent Java code would be + +[source,java] +---- +public interface BankService { + + @PreAuthorize("isAnonymous()") + public Account readAccount(Long id); + + @PreAuthorize("isAnonymous()") + public Account[] findAccounts(); + + @PreAuthorize("hasAuthority('ROLE_TELLER')") + public Account post(Account account, double amount); +} +---- + +Expression-based annotations are a good choice if you need to define simple rules that go beyond checking the role names against the user's list of authorities. + +[NOTE] +==== +The annotated methods will only be secured for instances which are defined as Spring beans (in the same application context in which method-security is enabled). If you want to secure instances which are not created by Spring (using the `new` operator, for example) then you need to use AspectJ. +==== + +[NOTE] +==== +You can enable more than one type of annotation in the same application, but only one type should be used for any interface or class as the behaviour will not be well-defined otherwise. If two annotations are found which apply to a particular method, then only one of them will be applied. +==== + +[[ns-protect-pointcut]] +====== Adding Security Pointcuts using protect-pointcut + +The use of `protect-pointcut` is particularly powerful, as it allows you to apply security to many beans with only a simple declaration. Consider the following example: + +[source,xml] +---- + + + +---- + +This will protect all methods on beans declared in the application context whose classes are in the `com.mycompany` package and whose class names end in "Service". Only users with the `ROLE_USER` role will be able to invoke these methods. As with URL matching, the most specific matches must come first in the list of pointcuts, as the first matching expression will be used. Security annotations take precedence over pointcuts. + +[[ns-access-manager]] +==== The Default AccessDecisionManager +This section assumes you have some knowledge of the underlying architecture for access-control within Spring Security. If you don't you can skip it and come back to it later, as this section is only really relevant for people who need to do some customization in order to use more than simple role-based security. + +When you use a namespace configuration, a default instance of `AccessDecisionManager` is automatically registered for you and will be used for making access decisions for method invocations and web URL access, based on the access attributes you specify in your `intercept-url` and `protect-pointcut` declarations (and in annotations if you are using annotation secured methods). + +The default strategy is to use an `AffirmativeBased` `AccessDecisionManager` with a `RoleVoter` and an `AuthenticatedVoter`. You can find out more about these in the chapter on <>. + + +[[ns-custom-access-mgr]] +===== Customizing the AccessDecisionManager +If you need to use a more complicated access control strategy then it is easy to set an alternative for both method and web security. + +For method security, you do this by setting the `access-decision-manager-ref` attribute on `global-method-security` to the `id` of the appropriate `AccessDecisionManager` bean in the application context: + +[source,xml] +---- + + ... + +---- + +The syntax for web security is the same, but on the `http` element: + +[source,xml] +---- + + ... + +---- + +[[ns-auth-manager]] +==== The Authentication Manager and the Namespace +The main interface which provides authentication services in Spring Security is the `AuthenticationManager`. This is usually an instance of Spring Security's `ProviderManager` class, which you may already be familiar with if you've used the framework before. If not, it will be covered later, in the <>. The bean instance is registered using the `authentication-manager` namespace element. You can't use a custom `AuthenticationManager` if you are using either HTTP or method security through the namespace, but this should not be a problem as you have full control over the `AuthenticationProvider` s that are used. + +You may want to register additional `AuthenticationProvider` beans with the `ProviderManager` and you can do this using the `` element with the `ref` attribute, where the value of the attribute is the name of the provider bean you want to add. For example: + +[source,xml] +---- + + + + + + ... + +---- + +Another common requirement is that another bean in the context may require a reference to the `AuthenticationManager`. You can easily register an alias for the `AuthenticationManager` and use this name elsewhere in your application context. + +[source,xml] +---- + + ... + + + + + ... + +---- + +[[sample-apps]] +=== Sample Applications +There are several sample web applications that are available with the project. To avoid an overly large download, only the "tutorial" and "contacts" samples are included in the distribution zip file. The others can be built directly from the source which you can obtain as described in <>. It's easy to build the project yourself and there's more information on the project web site at http://www.springsource.org/security/[ http://www.springsource.org/security/ ]. All paths referred to in this chapter are relative to the project source directory. + + +[[tutorial-sample]] +==== Tutorial Sample +The tutorial sample is a nice basic example to get you started. It uses simple namespace configuration throughout. The compiled application is included in the distribution zip file, ready to be deployed into your web container (`spring-security-samples-tutorial-3.1.x.war`). The <> authentication mechanism is used in combination with the commonly-used <> authentication provider to automatically remember the login using cookies. + +We recommend you start with the tutorial sample, as the XML is minimal and easy to follow. Most importantly, you can easily add this one XML file (and its corresponding `web.xml` entries) to your existing application. Only when this basic integration is achieved do we suggest you attempt adding in method authorization or domain object security. + + +[[contacts-sample]] +==== Contacts +The Contacts Sample is an advanced example in that it illustrates the more powerful features of domain object access control lists (ACLs) in addition to basic application security. The application provides an interface with which the users are able to administer a simple database of contacts (the domain objects). + +To deploy, simply copy the WAR file from Spring Security distribution into your container’s `webapps` directory. The war should be called `spring-security-samples-contacts-3.1.x.war` (the appended version number will vary depending on what release you are using). + +After starting your container, check the application can load. Visit http://localhost:8080/contacts (or whichever URL is appropriate for your web container and the WAR you deployed). + +Next, click "Debug". You will be prompted to authenticate, and a series of usernames and passwords are suggested on that page. Simply authenticate with any of these and view the resulting page. It should contain a success message similar to the following: +---- + +Security Debug Information + +Authentication object is of type: +org.springframework.security.authentication.UsernamePasswordAuthenticationToken + +Authentication object as a String: + +org.springframework.security.authentication.UsernamePasswordAuthenticationToken@1f127853: +Principal: org.springframework.security.core.userdetails.User@b07ed00: Username: rod; \ +Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; +credentialsNonExpired: true; AccountNonLocked: true; \ +Granted Authorities: ROLE_SUPERVISOR, ROLE_USER; \ +Password: [PROTECTED]; Authenticated: true; \ +Details: org.springframework.security.web.authentication.WebAuthenticationDetails@0: \ +RemoteIpAddress: 127.0.0.1; SessionId: 8fkp8t83ohar; \ +Granted Authorities: ROLE_SUPERVISOR, ROLE_USER + +Authentication object holds the following granted authorities: + +ROLE_SUPERVISOR (getAuthority(): ROLE_SUPERVISOR) +ROLE_USER (getAuthority(): ROLE_USER) + +Success! Your web filters appear to be properly configured! + +---- + + +Once you successfully receive the above message, return to the sample application's home page and click "Manage". You can then try out the application. Notice that only the contacts available to the currently logged on user are displayed, and only users with `ROLE_SUPERVISOR` are granted access to delete their contacts. Behind the scenes, the `MethodSecurityInterceptor` is securing the business objects. + +The application allows you to modify the access control lists associated with different contacts. Be sure to give this a try and understand how it works by reviewing the application context XML files. + + +[[ldap-sample]] +==== LDAP Sample +The LDAP sample application provides a basic configuration and sets up both a namespace configuration and an equivalent configuration using traditional beans, both in the same application context file. This means there are actually two identical authentication providers configured in this application. + + +[[openid-sample]] +==== OpenID Sample +The OpenID sample demonstrates how to use the namespace to configure OpenID and how to set up http://openid.net/specs/openid-attribute-exchange-1_0.html[attribute exchange] configurations for Google, Yahoo and MyOpenID identity providers (you can experiment with adding others if you wish). It uses the JQuery-based http://code.google.com/p/openid-selector/[openid-selector] project to provide a user-friendly login page which allows the user to easily select a provider, rather than typing in the full OpenID identifier. + +The application differs from normal authentication scenarios in that it allows any user to access the site (provided their OpenID authentication is successful). The first time you login, you will get a "Welcome [your name]"" message. If you logout and log back in (with the same OpenID identity) then this should change to "Welcome Back". This is achieved by using a custom `UserDetailsService` which assigns a standard role to any user and stores the identities internally in a map. Obviously a real application would use a database instead. Have a look at the source form more information. This class also takes into account the fact that different attributes may be returned from different providers and builds the name with which it addresses the user accordingly. + + +[[cas-sample]] +==== CAS Sample +The CAS sample requires that you run both a CAS server and CAS client. It isn't included in the distribution so you should check out the project code as described in <>. You'll find the relevant files under the `sample/cas` directory. There's also a `Readme.txt` file in there which explains how to run both the server and the client directly from the source tree, complete with SSL support. + + +[[jaas-sample]] +==== JAAS Sample +The JAAS sample is very simple example of how to use a JAAS LoginModule with Spring Security. The provided LoginModule will successfully authenticate a user if the username equals the password otherwise a LoginException is thrown. The AuthorityGranter used in this example always grants the role ROLE_USER. The sample application also demonstrates how to run as the JAAS Subject returned by the LoginModule by setting <> equal to "true". + + +[[preauth-sample]] +==== Pre-Authentication Sample +This sample application demonstrates how to wire up beans from the <> framework to make use of login information from a J2EE container. The user name and roles are those setup by the container. + +The code is in `samples/preauth`. + + +[[community]] +=== Spring Security Community + + +[[jira]] +==== Issue Tracking +Spring Security uses JIRA to manage bug reports and enhancement requests. If you find a bug, please log a report using JIRA. Do not log it on the support forum, mailing list or by emailing the project's developers. Such approaches are ad-hoc and we prefer to manage bugs using a more formal process. + +If possible, in your issue report please provide a JUnit test that demonstrates any incorrect behaviour. Or, better yet, provide a patch that corrects the issue. Similarly, enhancements are welcome to be logged in the issue tracker, although we only accept enhancement requests if you include corresponding unit tests. This is necessary to ensure project test coverage is adequately maintained. + +You can access the issue tracker at http://jira.springsource.org/browse/SEC[http://jira.springsource.org/browse/SEC]. + + +[[becoming-involved]] +==== Becoming Involved +We welcome your involvement in the Spring Security project. There are many ways of contributing, including reading the forum and responding to questions from other people, writing new code, improving existing code, assisting with documentation, developing samples or tutorials, or simply making suggestions. + + +[[further-info]] +==== Further Information +Questions and comments on Spring Security are welcome. You can use the Spring Community Forum web site at http://forum.springsource.org[http://forum.springsource.org] to discuss Spring Security with other users of the framework. Remember to use JIRA for bug reports, as explained above. + +[[overall-architecture]] +== Architecture and Implementation +Once you are familiar with setting up and running some namespace-configuration based applications, you may wish to develop more of an understanding of how the framework actually works behind the namespace facade. Like most software, Spring Security has certain central interfaces, classes and conceptual abstractions that are commonly used throughout the framework. In this part of the reference guide we will look at some of these and see how they work together to support authentication and access-control within Spring Security. + + +[[technical-overview]] +=== Technical Overview + + +[[runtime-environment]] +==== Runtime Environment +Spring Security 3.0 requires a Java 5.0 Runtime Environment or higher. As Spring Security aims to operate in a self-contained manner, there is no need to place any special configuration files into your Java Runtime Environment. In particular, there is no need to configure a special Java Authentication and Authorization Service (JAAS) policy file or place Spring Security into common classpath locations. + +Similarly, if you are using an EJB Container or Servlet Container there is no need to put any special configuration files anywhere, nor include Spring Security in a server classloader. All the required files will be contained within your application. + +This design offers maximum deployment time flexibility, as you can simply copy your target artifact (be it a JAR, WAR or EAR) from one system to another and it will immediately work. + + +[[core-components]] +==== Core Components +In Spring Security 3.0, the contents of the `spring-security-core` jar were stripped down to the bare minimum. It no longer contains any code related to web-application security, LDAP or namespace configuration. We'll take a look here at some of the Java types that you'll find in the core module. They represent the building blocks of the the framework, so if you ever need to go beyond a simple namespace configuration then it's important that you understand what they are, even if you don't actually need to interact with them directly. + + +===== SecurityContextHolder, SecurityContext and Authentication Objects +The most fundamental object is `SecurityContextHolder`. This is where we store details of the present security context of the application, which includes details of the principal currently using the application. By default the `SecurityContextHolder` uses a `ThreadLocal` to store these details, which means that the security context is always available to methods in the same thread of execution, even if the security context is not explicitly passed around as an argument to those methods. Using a `ThreadLocal` in this way is quite safe if care is taken to clear the thread after the present principal's request is processed. Of course, Spring Security takes care of this for you automatically so there is no need to worry about it. + +Some applications aren't entirely suitable for using a `ThreadLocal`, because of the specific way they work with threads. For example, a Swing client might want all threads in a Java Virtual Machine to use the same security context. `SecurityContextHolder` can be configured with a strategy on startup to specify how you would like the context to be stored. For a standalone application you would use the `SecurityContextHolder.MODE_GLOBAL` strategy. Other applications might want to have threads spawned by the secure thread also assume the same security identity. This is achieved by using `SecurityContextHolder.MODE_INHERITABLETHREADLOCAL`. You can change the mode from the default `SecurityContextHolder.MODE_THREADLOCAL` in two ways. The first is to set a system property, the second is to call a static method on `SecurityContextHolder`. Most applications won't need to change from the default, but if you do, take a look at the JavaDocs for `SecurityContextHolder` to learn more. + + +====== Obtaining information about the current user +Inside the `SecurityContextHolder` we store details of the principal currently interacting with the application. Spring Security uses an `Authentication` object to represent this information. You won't normally need to create an `Authentication` object yourself, but it is fairly common for users to query the `Authentication` object. You can use the following code block - from anywhere in your application - to obtain the name of the currently authenticated user, for example: + + +[source,java] +---- + +Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal(); + +if (principal instanceof UserDetails) { + String username = ((UserDetails)principal).getUsername(); +} else { + String username = principal.toString(); +} +---- + + +The object returned by the call to `getContext()` is an instance of the `SecurityContext` interface. This is the object that is kept in thread-local storage. As we'll see below, most authentication mechanisms withing Spring Security return an instance of `UserDetails` as the principal. + + +[[tech-userdetailsservice]] +===== The UserDetailsService +Another item to note from the above code fragment is that you can obtain a principal from the `Authentication` object. The principal is just an `Object`. Most of the time this can be cast into a `UserDetails` object. `UserDetails` is a core interface in Spring Security. It represents a principal, but in an extensible and application-specific way. Think of `UserDetails` as the adapter between your own user database and what Spring Security needs inside the `SecurityContextHolder`. Being a representation of something from your own user database, quite often you will cast the `UserDetails` to the original object that your application provided, so you can call business-specific methods (like`getEmail()`, `getEmployeeNumber()` and so on). + +By now you're probably wondering, so when do I provide a `UserDetails` object? How do I do that? I thought you said this thing was declarative and I didn't need to write any Java code - what gives? The short answer is that there is a special interface called `UserDetailsService`. The only method on this interface accepts a `String`-based username argument and returns a `UserDetails`: + +[source,java] +---- + + UserDetails loadUserByUsername(String username) throws UsernameNotFoundException; +---- + +This is the most common approach to loading information for a user within Spring + Security and you will see it used throughout the framework whenever information on a + user is required. + +On successful authentication, `UserDetails` is used to build the `Authentication` object that is stored in the `SecurityContextHolder` (more on this <>). The good news is that we provide a number of `UserDetailsService` implementations, including one that uses an in-memory map (`InMemoryDaoImpl`) and another that uses JDBC (`JdbcDaoImpl`). Most users tend to write their own, though, with their implementations often simply sitting on top of an existing Data Access Object (DAO) that represents their employees, customers, or other users of the application. Remember the advantage that whatever your `UserDetailsService` returns can always be obtained from the `SecurityContextHolder` using the above code fragment. + +[NOTE] +==== + +There is often some confusion about `UserDetailsService`. It is purely a DAO for user data and performs no other function other than to supply that data to other components within the framework. In particular, it __does not__ authenticate the user, which is done by the `AuthenticationManager`. In many cases it makes more sense to <> directly if you require a custom authentication process. + +==== + + +[[tech-granted-authority]] +===== GrantedAuthority +Besides the principal, another important method provided by `Authentication` is `getAuthorities()`. This method provides an array of `GrantedAuthority` objects. A `GrantedAuthority` is, not surprisingly, an authority that is granted to the principal. Such authorities are usually "roles", such as `ROLE_ADMINISTRATOR` or `ROLE_HR_SUPERVISOR`. These roles are later on configured for web authorization, method authorization and domain object authorization. Other parts of Spring Security are capable of interpreting these authorities, and expect them to be present. `GrantedAuthority` objects are usually loaded by the `UserDetailsService`. + +Usually the `GrantedAuthority` objects are application-wide permissions. They are not specific to a given domain object. Thus, you wouldn't likely have a `GrantedAuthority` to represent a permission to `Employee` object number 54, because if there are thousands of such authorities you would quickly run out of memory (or, at the very least, cause the application to take a long time to authenticate a user). Of course, Spring Security is expressly designed to handle this common requirement, but you'd instead use the project's domain object security capabilities for this purpose. + + +===== Summary +Just to recap, the major building blocks of Spring Security that we've seen so far are: + + +* `SecurityContextHolder`, to provide access to the `SecurityContext`. + +* `SecurityContext`, to hold the `Authentication` and possibly request-specific security information. + +* `Authentication`, to represent the principal in a Spring Security-specific manner. + +* `GrantedAuthority`, to reflect the application-wide permissions granted to a principal. + +* `UserDetails`, to provide the necessary information to build an Authentication object from your application's DAOs or other source of security data. + +* `UserDetailsService`, to create a `UserDetails` when passed in a `String`-based username (or certificate ID or the like). + + + +Now that you've gained an understanding of these repeatedly-used components, let's take a closer look at the process of authentication. + + +[[tech-intro-authentication]] +==== Authentication +Spring Security can participate in many different authentication environments. While we recommend people use Spring Security for authentication and not integrate with existing Container Managed Authentication, it is nevertheless supported - as is integrating with your own proprietary authentication system. + + +===== What is authentication in Spring Security? +Let's consider a standard authentication scenario that everyone is familiar with. + +. A user is prompted to log in with a username and password. +. The system (successfully) verifies that the password is correct for the username. +. The context information for that user is obtained (their list of roles and so on). +. A security context is established for the user +. The user proceeds, potentially to perform some operation which is potentially protected by an access control mechanism which checks the required permissions for the operation against the current security context information. + + +The first three items constitute the authentication process so we'll take a look at how these take place within Spring Security. + +. The username and password are obtained and combined into an instance of `UsernamePasswordAuthenticationToken` (an instance of the `Authentication` interface, which we saw earlier). +. The token is passed to an instance of `AuthenticationManager` for validation. +. The `AuthenticationManager` returns a fully populated `Authentication` instance on successful authentication. +. The security context is established by calling `SecurityContextHolder.getContext().setAuthentication(...)`, passing in the returned authentication object. + +From that point on, the user is considered to be authenticated. Let's look at some code as an example. + +[source,java] +---- +import org.springframework.security.authentication.*; +import org.springframework.security.core.*; +import org.springframework.security.core.authority.SimpleGrantedAuthority; +import org.springframework.security.core.context.SecurityContextHolder; + +public class AuthenticationExample { + private static AuthenticationManager am = new SampleAuthenticationManager(); + + public static void main(String[] args) throws Exception { + BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); + + while(true) { + System.out.println("Please enter your username:"); + String name = in.readLine(); + System.out.println("Please enter your password:"); + String password = in.readLine(); + try { + Authentication request = new UsernamePasswordAuthenticationToken(name, password); + Authentication result = am.authenticate(request); + SecurityContextHolder.getContext().setAuthentication(result); + break; + } catch(AuthenticationException e) { + System.out.println("Authentication failed: " + e.getMessage()); + } + } + System.out.println("Successfully authenticated. Security context contains: " + + SecurityContextHolder.getContext().getAuthentication()); + } +} + +class SampleAuthenticationManager implements AuthenticationManager { + static final List AUTHORITIES = new ArrayList(); + + static { + AUTHORITIES.add(new SimpleGrantedAuthority("ROLE_USER")); + } + + public Authentication authenticate(Authentication auth) throws AuthenticationException { + if (auth.getName().equals(auth.getCredentials())) { + return new UsernamePasswordAuthenticationToken(auth.getName(), + auth.getCredentials(), AUTHORITIES); + } + throw new BadCredentialsException("Bad Credentials"); + } +} +---- + +Here + we have written a little program that asks the user to enter a username and password + and performs the above sequence. The + `AuthenticationManager` which we've implemented here will authenticate any user whose username and password are the same. It assigns a single role to every user. The output from the above will be something like: + +[source,txt] +---- + +Please enter your username: +bob +Please enter your password: +password +Authentication failed: Bad Credentials +Please enter your username: +bob +Please enter your password: +bob +Successfully authenticated. Security context contains: \ + org.springframework.security.authentication.UsernamePasswordAuthenticationToken@441d0230: \ + Principal: bob; Password: [PROTECTED]; \ + Authenticated: true; Details: null; \ + Granted Authorities: ROLE_USER + +---- + + + +Note that you don't normally need to write any code like this. The process will normally occur internally, in a web authentication filter for example. We've just included the code here to show that the question of what actually constitutes authentication in Spring Security has quite a simple answer. A user is authenticated when the `SecurityContextHolder` contains a fully populated `Authentication` object. + + +===== Setting the SecurityContextHolder Contents Directly +In fact, Spring Security doesn't mind how you put the `Authentication` object inside the `SecurityContextHolder`. The only critical requirement is that the `SecurityContextHolder` contains an `Authentication` which represents a principal before the `AbstractSecurityInterceptor` (which we'll see more about later) needs to authorize a user operation. + +You can (and many users do) write their own filters or MVC controllers to provide interoperability with authentication systems that are not based on Spring Security. For example, you might be using Container-Managed Authentication which makes the current user available from a ThreadLocal or JNDI location. Or you might work for a company that has a legacy proprietary authentication system, which is a corporate "standard" over which you have little control. In situations like this it's quite easy to get Spring Security to work, and still provide authorization capabilities. All you need to do is write a filter (or equivalent) that reads the third-party user information from a location, build a Spring Security-specific `Authentication` object, and put it into the `SecurityContextHolder`. In this case you also need to think about things which are normally taken care of automatically by the built-in authentication infrastructure. For example, you might need to pre-emptively create an HTTP session to <>, before you write the response to the client footnote:[It isn't possible to create a session once the response has been committed.]. + +If you're wondering how the `AuthenticationManager` is implemented in a real world example, we'll look at that in the <>. + + +[[tech-intro-web-authentication]] +==== Authentication in a Web Application +Now let's explore the situation where you are using Spring Security in a web application (without `web.xml` security enabled). How is a user authenticated and the security context established? + +Consider a typical web application's authentication process: + + +. You visit the home page, and click on a link. +. A request goes to the server, and the server decides that you've asked for a protected resource. +. As you're not presently authenticated, the server sends back a response indicating that you must authenticate. The response will either be an HTTP response code, or a redirect to a particular web page. +. Depending on the authentication mechanism, your browser will either redirect to the specific web page so that you can fill out the form, or the browser will somehow retrieve your identity (via a BASIC authentication dialogue box, a cookie, a X.509 certificate etc.). +. The browser will send back a response to the server. This will either be an HTTP POST containing the contents of the form that you filled out, or an HTTP header containing your authentication details. +. Next the server will decide whether or not the presented credentials are valid. If they're valid, the next step will happen. If they're invalid, usually your browser will be asked to try again (so you return to step two above). +. The original request that you made to cause the authentication process will be retried. Hopefully you've authenticated with sufficient granted authorities to access the protected resource. If you have sufficient access, the request will be successful. Otherwise, you'll receive back an HTTP error code 403, which means "forbidden". + +Spring Security has distinct classes responsible for most of the steps described above. The main participants (in the order that they are used) are the `ExceptionTranslationFilter`, an `AuthenticationEntryPoint` and an "authentication mechanism", which is responsible for calling the `AuthenticationManager` which we saw in the previous section. + + +===== ExceptionTranslationFilter +`ExceptionTranslationFilter` is a Spring Security filter that has responsibility for detecting any Spring Security exceptions that are thrown. Such exceptions will generally be thrown by an `AbstractSecurityInterceptor`, which is the main provider of authorization services. We will discuss `AbstractSecurityInterceptor` in the next section, but for now we just need to know that it produces Java exceptions and knows nothing about HTTP or how to go about authenticating a principal. Instead the `ExceptionTranslationFilter` offers this service, with specific responsibility for either returning error code 403 (if the principal has been authenticated and therefore simply lacks sufficient access - as per step seven above), or launching an `AuthenticationEntryPoint` (if the principal has not been authenticated and therefore we need to go commence step three). + + +[[tech-intro-auth-entry-point]] +===== AuthenticationEntryPoint +The `AuthenticationEntryPoint` is responsible for step three in the above list. As you can imagine, each web application will have a default authentication strategy (well, this can be configured like nearly everything else in Spring Security, but let's keep it simple for now). Each major authentication system will have its own `AuthenticationEntryPoint` implementation, which typically performs one of the actions described in step 3. + + +===== Authentication Mechanism +Once your browser submits your authentication credentials (either as an HTTP form post or HTTP header) there needs to be something on the server that"collects" these authentication details. By now we're at step six in the above list. In Spring Security we have a special name for the function of collecting authentication details from a user agent (usually a web browser), referring to it as the "authentication mechanism". Examples are form-base login and Basic authentication. Once the authentication details have been collected from the user agent, an `Authentication`"request" object is built and then presented to the `AuthenticationManager`. + +After the authentication mechanism receives back the fully-populated `Authentication` object, it will deem the request valid, put the `Authentication` into the `SecurityContextHolder`, and cause the original request to be retried (step seven above). If, on the other hand, the `AuthenticationManager` rejected the request, the authentication mechanism will ask the user agent to retry (step two above). + + +[[tech-intro-sec-context-persistence]] +===== Storing the SecurityContext between requests +Depending on the type of application, there may need to be a strategy in place to store the security context between user operations. In a typical web application, a user logs in once and is subsequently identified by their session Id. The server caches the principal information for the duration session. In Spring Security, the responsibility for storing the `SecurityContext` between requests falls to the `SecurityContextPersistenceFilter`, which by default stores the context as an `HttpSession` attribute between HTTP requests. It restores the context to the `SecurityContextHolder` for each request and, crucially, clears the `SecurityContextHolder` when the request completes. You shouldn't interact directly with the `HttpSession` for security purposes. There is simply no justification for doing so - always use the `SecurityContextHolder` instead. + +Many other types of application (for example, a stateless RESTful web service) do not use HTTP sessions and will re-authenticate on every request. However, it is still important that the `SecurityContextPersistenceFilter` is included in the chain to make sure that the `SecurityContextHolder` is cleared after each request. + +[NOTE] +==== +In an application which receives concurrent requests in a single session, the same `SecurityContext` instance will be shared between threads. Even though a `ThreadLocal` is being used, it is the same instance that is retrieved from the `HttpSession` for each thread. This has implications if you wish to temporarily change the context under which a thread is running. If you just use `SecurityContextHolder.getContext()`, and call `setAuthentication(anAuthentication)` on the returned context object, then the `Authentication` object will change in __all__ concurrent threads which share the same `SecurityContext` instance. You can customize the behaviour of `SecurityContextPersistenceFilter` to create a completely new `SecurityContext` for each request, preventing changes in one thread from affecting another. Alternatively you can create a new instance just at the point where you temporarily change the context. The method `SecurityContextHolder.createEmptyContext()` always returns a new context instance. +==== + +[[tech-intro-access-control]] +==== Access-Control (Authorization) in Spring Security +The main interface responsible for making access-control decisions in Spring Security is the `AccessDecisionManager`. It has a `decide` method which takes an `Authentication` object representing the principal requesting access, a "secure object" (see below) and a list of security metadata attributes which apply for the object (such as a list of roles which are required for access to be granted). + + +===== Security and AOP Advice +If you're familiar with AOP, you'd be aware there are different types of advice available: before, after, throws and around. An around advice is very useful, because an advisor can elect whether or not to proceed with a method invocation, whether or not to modify the response, and whether or not to throw an exception. Spring Security provides an around advice for method invocations as well as web requests. We achieve an around advice for method invocations using Spring's standard AOP support and we achieve an around advice for web requests using a standard Filter. + +For those not familiar with AOP, the key point to understand is that Spring Security can help you protect method invocations as well as web requests. Most people are interested in securing method invocations on their services layer. This is because the services layer is where most business logic resides in current-generation J2EE applications. If you just need to secure method invocations in the services layer, Spring's standard AOP will be adequate. If you need to secure domain objects directly, you will likely find that AspectJ is worth considering. + +You can elect to perform method authorization using AspectJ or Spring AOP, or you can elect to perform web request authorization using filters. You can use zero, one, two or three of these approaches together. The mainstream usage pattern is to perform some web request authorization, coupled with some Spring AOP method invocation authorization on the services layer. + + +[[secure-objects]] +===== Secure Objects and the AbstractSecurityInterceptor +So what __is__ a "secure object" anyway? Spring Security uses the term to refer to any object that can have security (such as an authorization decision) applied to it. The most common examples are method invocations and web requests. + +Each supported secure object type has its own interceptor class, which is a subclass of `AbstractSecurityInterceptor`. Importantly, by the time the `AbstractSecurityInterceptor` is called, the `SecurityContextHolder` will contain a valid `Authentication` if the principal has been authenticated. + +`AbstractSecurityInterceptor` provides a consistent workflow for handling secure object requests, typically: + +. Look up the "configuration attributes" associated with the present request +. Submitting the secure object, current `Authentication` and configuration attributes to the `AccessDecisionManager` for an authorization decision +. Optionally change the `Authentication` under which the invocation takes place +. Allow the secure object invocation to proceed (assuming access was granted) +. Call the `AfterInvocationManager` if configured, once the invocation has returned. If the invocation raised an exception, the `AfterInvocationManager` will not be invoked. + +[[tech-intro-config-attributes]] +====== What are Configuration Attributes? +A "configuration attribute" can be thought of as a String that has special meaning to the classes used by`AbstractSecurityInterceptor`. They are represented by the interface `ConfigAttribute` within the framework. They may be simple role names or have more complex meaning, depending on the how sophisticated the `AccessDecisionManager` implementation is. The `AbstractSecurityInterceptor` is configured with a `SecurityMetadataSource` which it uses to look up the attributes for a secure object. Usually this configuration will be hidden from the user. Configuration attributes will be entered as annotations on secured methods or as access attributes on secured URLs. For example, when we saw something like `` in the namespace introduction, this is saying that the configuration attributes `ROLE_A` and `ROLE_B` apply to web requests matching the given pattern. In practice, with the default `AccessDecisionManager` configuration, this means that anyone who has a `GrantedAuthority` matching either of these two attributes will be allowed access. Strictly speaking though, they are just attributes and the interpretation is dependent on the `AccessDecisionManager` implementation. The use of the prefix `ROLE_` is a marker to indicate that these attributes are roles and should be consumed by Spring Security's`RoleVoter`. This is only relevant when a voter-based `AccessDecisionManager` is in use. We'll see how the `AccessDecisionManager` is implemented in the <>. + + +====== RunAsManager +Assuming `AccessDecisionManager` decides to allow the request, the `AbstractSecurityInterceptor` will normally just proceed with the request. Having said that, on rare occasions users may want to replace the `Authentication` inside the `SecurityContext` with a different `Authentication`, which is handled by the `AccessDecisionManager` calling a `RunAsManager`. This might be useful in reasonably unusual situations, such as if a services layer method needs to call a remote system and present a different identity. Because Spring Security automatically propagates security identity from one server to another (assuming you're using a properly-configured RMI or HttpInvoker remoting protocol client), this may be useful. + + +====== AfterInvocationManager +Following the secure object invocation proceeding and then returning - which may mean a method invocation completing or a filter chain proceeding - the `AbstractSecurityInterceptor` gets one final chance to handle the invocation. At this stage the `AbstractSecurityInterceptor` is interested in possibly modifying the return object. We might want this to happen because an authorization decision couldn't be made "on the way in" to a secure object invocation. Being highly pluggable, `AbstractSecurityInterceptor` will pass control to an `AfterInvocationManager` to actually modify the object if needed. This class can even entirely replace the object, or throw an exception, or not change it in any way as it chooses. The after-invocation checks will only be executed if the invocation is successful. If an exception occurs, the additional checks will be skipped. + +`AbstractSecurityInterceptor` and its related objects are shown in <> + +[[abstract-security-interceptor]] +.Security interceptors and the “secure object” model +image::images/security-interception.png[Abstract Security Interceptor] + +====== Extending the Secure Object Model +Only developers contemplating an entirely new way of intercepting and authorizing requests would need to use secure objects directly. For example, it would be possible to build a new secure object to secure calls to a messaging system. Anything that requires security and also provides a way of intercepting a call (like the AOP around advice semantics) is capable of being made into a secure object. Having said that, most Spring applications will simply use the three currently supported secure object types (AOP Alliance `MethodInvocation`, AspectJ `JoinPoint` and web request `FilterInvocation`) with complete transparency. + + +[[localization]] +==== Localization +Spring Security supports localization of exception messages that end users are likely to see. If your application is designed for English-speaking users, you don't need to do anything as by default all Security Security messages are in English. If you need to support other locales, everything you need to know is contained in this section. + +All exception messages can be localized, including messages related to authentication failures and access being denied (authorization failures). Exceptions and logging messages that are focused on developers or system deployers (including incorrect attributes, interface contract violations, using incorrect constructors, startup time validation, debug-level logging) are not localized and instead are hard-coded in English within Spring Security's code. + +Shipping in the `spring-security-core-xx.jar` you will find an `org.springframework.security` package that in turn contains a `messages.properties` file, as well as localized versions for some common languages. This should be referred to by your`ApplicationContext`, as Spring Security classes implement Spring's `MessageSourceAware` interface and expect the message resolver to be dependency injected at application context startup time. Usually all you need to do is register a bean inside your application context to refer to the messages. An example is shown below: + +[source,xml] +---- + + + +---- + +The `messages.properties` is named in accordance with standard resource bundles and represents the default language supported by Spring Security messages. This default file is in English. + +If you wish to customize the `messages.properties` file, or support other languages, you should copy the file, rename it accordingly, and register it inside the above bean definition. There are not a large number of message keys inside this file, so localization should not be considered a major initiative. If you do perform localization of this file, please consider sharing your work with the community by logging a JIRA task and attaching your appropriately-named localized version of `messages.properties`. + +Spring Security relies on Spring's localization support in order to actually lookup the appropriate message. In order for this to work, you have to make sure that the locale from the incoming request is stored in Spring's `org.springframework.context.i18n.LocaleContextHolder`. Spring MVC's `DispatcherServlet` does this for your application automatically, but since Spring Security's filters are invoked before this, the `LocaleContextHolder` needs to be set up to contain the correct `Locale` before the filters are called. You can either do this in a filter yourself (which must come before the Spring Security filters in`web.xml`) or you can use Spring's `RequestContextFilter`. Please refer to the Spring Framework documentation for further details on using localization with Spring. + +The "contacts" sample application is set up to use localized messages. + + +[[core-services]] +=== Core Services +Now that we have a high-level overview of the Spring Security architecture and its core classes, let's take a closer look at one or two of the core interfaces and their implementations, in particular the `AuthenticationManager`, `UserDetailsService` and the `AccessDecisionManager`. These crop up regularly throughout the remainder of this document so it's important you know how they are configured and how they operate. + + +[[core-services-authentication-manager]] +==== The AuthenticationManager, ProviderManager and AuthenticationProvider +The `AuthenticationManager` is just an interface, so the implementation can be anything we choose, but how does it work in practice? What if we need to check multiple authentication databases or a combination of different authentication services such as a database and an LDAP server? + +The default implementation in Spring Security is called `ProviderManager` and rather than handling the authentication request itself, it delegates to a list of configured `AuthenticationProvider` s, each of which is queried in turn to see if it can perform the authentication. Each provider will either throw an exception or return a fully populated `Authentication` object. Remember our good friends, `UserDetails` and `UserDetailsService`? If not, head back to the previous chapter and refresh your memory. The most common approach to verifying an authentication request is to load the corresponding `UserDetails` and check the loaded password against the one that has been entered by the user. This is the approach used by the `DaoAuthenticationProvider` (see below). The loaded `UserDetails` object - and particularly the `GrantedAuthority` s it contains - will be used when building the fully populated `Authentication` object which is returned from a successful authentication and stored in the `SecurityContext`. + +If you are using the namespace, an instance of `ProviderManager` is created and maintained internally, and you add providers to it by using the namespace authentication provider elements (see <>). In this case, you should not declare a `ProviderManager` bean in your application context. However, if you are not using the namespace then you would declare it like so: + +[source,xml] +---- + + + + + + + + + + +---- + +In the above example we have three providers. They are tried in the order shown (which is implied by the use of a `List`), with each provider able to attempt authentication, or skip authentication by simply returning `null`. If all implementations return null, the `ProviderManager` will throw a `ProviderNotFoundException`. If you're interested in learning more about chaining providers, please refer to the `ProviderManager` JavaDocs. + +Authentication mechanisms such as a web form-login processing filter are injected with a reference to the `ProviderManager` and will call it to handle their authentication requests. The providers you require will sometimes be interchangeable with the authentication mechanisms, while at other times they will depend on a specific authentication mechanism. For example, `DaoAuthenticationProvider` and `LdapAuthenticationProvider` are compatible with any mechanism which submits a simple username/password authentication request and so will work with form-based logins or HTTP Basic authentication. On the other hand, some authentication mechanisms create an authentication request object which can only be interpreted by a single type of `AuthenticationProvider`. An example of this would be JA-SIG CAS, which uses the notion of a service ticket and so can therefore only be authenticated by a `CasAuthenticationProvider`. You needn't be too concerned about this, because if you forget to register a suitable provider, you'll simply receive a `ProviderNotFoundException` when an attempt to authenticate is made. + + +[[core-services-erasing-credentials]] +===== Erasing Credentials on Successful Authentication +By default (from Spring Security 3.1 onwards) the `ProviderManager` will attempt to clear any sensitive credentials information from the `Authentication` object which is returned by a successful authentication request. This prevents information like passwords being retained longer than necessary. + +This may cause issues when you are using a cache of user objects, for example, to improve performance in a stateless application. If the `Authentication` contains a reference to an object in the cache (such as a `UserDetails` instance) and this has its credentials removed, then it will no longer be possible to authenticate against the cached value. You need to take this into account if you are using a cache. An obvious solution is to make a copy of the object first, either in the cache implementation or in the `AuthenticationProvider` which creates the returned `Authentication` object. Alternatively, you can disable the `eraseCredentialsAfterAuthentication` property on `ProviderManager`. See the Javadoc for more information. + + +[[core-services-dao-provider]] +===== DaoAuthenticationProvider +The simplest `AuthenticationProvider` implemented by Spring Security is `DaoAuthenticationProvider`, which is also one of the earliest supported by the framework. It leverages a `UserDetailsService` (as a DAO) in order to lookup the username, password and `GrantedAuthority` s. It authenticates the user simply by comparing the password submitted in a `UsernamePasswordAuthenticationToken` against the one loaded by the `UserDetailsService`. Configuring the provider is quite simple: + +[source,xml] +---- + + + + + +---- + +The `PasswordEncoder` is optional. A `PasswordEncoder` provides encoding and decoding of passwords presented in the `UserDetails` object that is returned from the configured `UserDetailsService`. This will be discussed in more detail <>. + + +==== UserDetailsService Implementations +As mentioned in the earlier in this reference guide, most authentication providers take advantage of the `UserDetails` and `UserDetailsService` interfaces. Recall that the contract for `UserDetailsService` is a single method: + +[source,java] +---- +UserDetails loadUserByUsername(String username) throws UsernameNotFoundException; +---- + +The returned `UserDetails` is an interface that provides getters that guarantee non-null provision of authentication information such as the username, password, granted authorities and whether the user account is enabled or disabled. Most authentication providers will use a`UserDetailsService`, even if the username and password are not actually used as part of the authentication decision. They may use the returned `UserDetails` object just for its `GrantedAuthority` information, because some other system (like LDAP or X.509 or CAS etc) has undertaken the responsibility of actually validating the credentials. + +Given `UserDetailsService` is so simple to implement, it should be easy for users to retrieve authentication information using a persistence strategy of their choice. Having said that, Spring Security does include a couple of useful base implementations, which we'll look at below. + + +[[core-services-in-memory-service]] +===== In-Memory Authentication +Is easy to use create a custom `UserDetailsService` implementation that extracts information from a persistence engine of choice, but many applications do not require such complexity. This is particularly true if you're building a prototype application or just starting integrating Spring Security, when you don't really want to spend time configuring databases or writing `UserDetailsService` implementations. For this sort of situation, a simple option is to use the `user-service` element from the security <>: + +[source,xml] +---- + + + + +---- + +This also supports the use of an external properties file: + +[source,xml] +---- + +---- + +The properties file should contain entries in the form + +[source,txt] +---- +username=password,grantedAuthority[,grantedAuthority][,enabled|disabled] +---- + +For example + +[source,txt] +---- +jimi=jimispassword,ROLE_USER,ROLE_ADMIN,enabled +bob=bobspassword,ROLE_USER,enabled +---- + +[[core-services-jdbc-user-service]] +===== JdbcDaoImpl +Spring Security also includes a `UserDetailsService` that can obtain authentication information from a JDBC data source. Internally Spring JDBC is used, so it avoids the complexity of a fully-featured object relational mapper (ORM) just to store user details. If your application does use an ORM tool, you might prefer to write a custom `UserDetailsService` to reuse the mapping files you've probably already created. Returning to `JdbcDaoImpl`, an example configuration is shown below: + +[source,xml] +---- + + + + + + + + + + +---- + +You can use different relational database management systems by modifying the `DriverManagerDataSource` shown above. You can also use a global data source obtained from JNDI, as with any other Spring configuration. + +====== Authority Groups +By default, `JdbcDaoImpl` loads the authorities for a single user with the assumption that the authorities are mapped directly to users (see the <>). An alternative approach is to partition the authorities into groups and assign groups to the user. Some people prefer this approach as a means of administering user rights. See the `JdbcDaoImpl` Javadoc for more information on how to enable the use of group authorities. The group schema is also included in the appendix. + + +[[core-services-password-encoding]] +==== Password Encoding +Spring Security's `PasswordEncoder` interface is used to support the use of passwords which are encoded in some way in persistent storage. You should never store passwords in plain text. Always use a one-way password hashing algorithm such as bcrypt which uses a built-in salt value which is different for each stored password. Do not use a plain hash function such as MD5 or SHA, or even a salted version. Bcrypt is deliberately designed to be slow and to hinder offline password cracking, whereas standard hash algorithms are fast and can easily be used to test thousands of passwords in parallel on custom hardware. You might think this doesn't apply to you since your password database is secure and offline attacks aren't a risk. If so, do some research and read up on all the high-profile sites which have been compromised in this way and have been pilloried for storing their passwords insecurely. It's best to be on the safe side. Using `org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder"` is a good choice for security. There are also compatible implementations in other common programming languages so it a good choice for interoperability too. + +If you are using a legacy system which already has hashed passwords, then you will need to use an encoder which matches your current algorithm, at least until you can migrate your users to a more secure scheme (usually this will involve asking the user to set a new password, since hashes are irreversible). Spring Security has a package containing legacy password encoding implementation, namely, `org.springframework.security.authentication.encoding`. The `DaoAuthenticationProvider` can be injected with either the new or legacy `PasswordEncoder` types. + + +===== What is a hash? +Password hashing is not unique to Spring Security but is a common source of confusion for users who are not familiar with the concept. A hash (or digest) algorithm is a one-way function which produces a piece of fixed-length output data (the hash) from some input data, such as a password. As an example, the MD5 hash of the string "password" (in hexadecimal) is + +[source,txt] +---- +5f4dcc3b5aa765d61d8327deb882cf99 +---- + +A hash is "one-way" in the sense that it is very difficult (effectively impossible) to obtain the original input given the hash value, or indeed any possible input which would produce that hash value. This property makes hash values very useful for authentication purposes. They can be stored in your user database as an alternative to plaintext passwords and even if the values are compromised they do not immediately reveal a password which can be used to login. Note that this also means you have no way of recovering the password once it is encoded. + +===== Adding Salt to a Hash +One potential problem with the use of password hashes that it is relatively easy to get round the one-way property of the hash if a common word is used for the input. People tend to choose similar passwords and huge dictionaries of these from previously hacked sites are available online. For example, if you search for the hash value `5f4dcc3b5aa765d61d8327deb882cf99` using google, you will quickly find the original word "password". In a similar way, an attacker can build a dictionary of hashes from a standard word list and use this to lookup the original password. One way to help prevent this is to have a suitably strong password policy to try to prevent common words from being used. Another is to use a"salt" when calculating the hashes. This is an additional string of known data for each user which is combined with the password before calculating the hash. Ideally the data should be as random as possible, but in practice any salt value is usually preferable to none. Using a salt means that an attacker has to build a separate dictionary of hashes for each salt value, making the attack more complicated (but not impossible). + +Bcrypt automatically generates a random salt value for each password when it is encoded, and stores it in the bcrypt string in a standard format. + +[NOTE] +==== +The legacy approach to handling salt was to inject a `SaltSource` into the `DaoAuthenticationProvider`, which would obtain a salt value for a particular user and pass it to the `PasswordEncoder`. Using bcrypt means you don't have worry about the details of salt handling (such as where the the value is stored), as it is all done internally. So we'd strongly recommend you use bcrypt unless you already have a system in place which stores the salt separately. +==== + +===== Hashing and Authentication +When an authentication provider (such as Spring Security's `DaoAuthenticationProvider`) needs to check the password in a submitted authentication request against the known value for a user, and the stored password is encoded in some way, then the submitted value must be encoded using exactly the same algorithm. It's up to you to check that these are compatible as Spring Security has no control over the persistent values. If you add password hashing to your authentication configuration in Spring Security, and your database contains plaintext passwords, then there is no way authentication can succeed. Even if you are aware that your database is using MD5 to encode the passwords, for example, and your application is configured to use Spring Security's `Md5PasswordEncoder`, there are still things that can go wrong. The database may have the passwords encoded in Base 64, for example while the encoder is using hexadecimal strings (the default). Alternatively your database may be using upper-case while the output from the encoder is lower-case. Make sure you write a test to check the output from your configured password encoder with a known password and salt combination and check that it matches the database value before going further and attempting to authenticate through your application. Using a standard like bcrypt will avoid these issues. + +If you want to generate encoded passwords directly in Java for storage in your user database, then you can use the `encode` method on the `PasswordEncoder`. + + +[[web-app-security]] +== Web Application Security +Most Spring Security users will be using the framework in applications which make user of HTTP and the Servlet API. In this part, we'll take a look at how Spring Security provides authentication and access-control features for the web layer of an application. We'll look behind the facade of the namespace and see which classes and interfaces are actually assembled to provide web-layer security. In some situations it is necessary to use traditional bean configuration to provide full control over the configuration, so we'll also see how to configure these classes directly without the namespace. + +[[security-filter-chain]] +=== The Security Filter Chain +Spring Security's web infrastructure is based entirely on standard servlet filters. It doesn't use servlets or any other servlet-based frameworks (such as Spring MVC) internally, so it has no strong links to any particular web technology. It deals in `HttpServletRequest` s and `HttpServletResponse` s and doesn't care whether the requests come from a browser, a web service client, an `HttpInvoker` or an AJAX application. + +Spring Security maintains a filter chain internally where each of the filters has a particular responsibility and filters are added or removed from the configuration depending on which services are required. The ordering of the filters is important as there are dependencies between them. If you have been using <>, then the filters are automatically configured for you and you don't have to define any Spring beans explicitly but here may be times when you want full control over the security filter chain, either because you are using features which aren't supported in the namespace, or you are using your own customized versions of classes. + + +[[delegating-filter-proxy]] +==== DelegatingFilterProxy +When using servlet filters, you obviously need to declare them in your `web.xml`, or they will be ignored by the servlet container. In Spring Security, the filter classes are also Spring beans defined in the application context and thus able to take advantage of Spring's rich dependency-injection facilities and lifecycle interfaces. Spring's `DelegatingFilterProxy` provides the link between `web.xml` and the application context. + +When using `DelegatingFilterProxy`, you will see something like this in the `web.xml` file: + +[source,xml] +---- + + myFilter + org.springframework.web.filter.DelegatingFilterProxy + + + + myFilter + /* + +---- + +Notice that the filter is actually a `DelegatingFilterProxy`, and not the class that will actually implement the logic of the filter. What `DelegatingFilterProxy` does is delegate the `Filter`'s methods through to a bean which is obtained from the Spring application context. This enables the bean to benefit from the Spring web application context lifecycle support and configuration flexibility. The bean must implement `javax.servlet.Filter` and it must have the same name as that in the `filter-name` element. Read the Javadoc for `DelegatingFilterProxy` for more information + + +[[filter-chain-proxy]] +==== FilterChainProxy +Spring Security's web infrastructure should only be used by delegating to an instance of `FilterChainProxy`. The security filters should not be used by themselves. In theory you could declare each Spring Security filter bean that you require in your application context file and add a corresponding `DelegatingFilterProxy` entry to `web.xml` for each filter, making sure that they are ordered correctly, but this would be cumbersome and would clutter up the `web.xml` file quickly if you have a lot of filters. `FilterChainProxy` lets us add a single entry to `web.xml` and deal entirely with the application context file for managing our web security beans. It is wired using a`DelegatingFilterProxy`, just like in the example above, but with the `filter-name` set to the bean name "filterChainProxy". The filter chain is then declared in the application context with the same bean name. Here's an example: + +[source,xml] +---- + + + + + + + + +---- + +The namespace element `filter-chain` is used for convenience to set up the security filter chain(s) which are required within the application. footnote:[Note that you'll need to include the security namespace in your application context XML file in order to use this syntax. The older syntax which used a `filter-chain-map` is still supported, but is deprecated in favour of the constructor argument injection.]. It maps a particular URL pattern to a list of filters built up from the bean names specified in the `filters` element, and combines them in a bean of type `SecurityFilterChain`. The `pattern` attribute takes an Ant Paths and the most specific URIs should appear first footnote:[Instead of a path pattern, the `request-matcher-ref` attribute can be used to specify a `RequestMatcher` instance for more powerful matching]. At runtime the `FilterChainProxy` will locate the first URI pattern that matches the current web request and the list of filter beans specified by the `filters` attribute will be applied to that request. The filters will be invoked in the order they are defined, so you have complete control over the filter chain which is applied to a particular URL. + +You may have noticed we have declared two `SecurityContextPersistenceFilter` s in the filter chain ( `ASC` is short for `allowSessionCreation`, a property of `SecurityContextPersistenceFilter`). As web services will never present a `jsessionid` on future requests, creating `HttpSession` s for such user agents would be wasteful. If you had a high-volume application which required maximum scalability, we recommend you use the approach shown above. For smaller applications, using a single `SecurityContextPersistenceFilter` (with its default `allowSessionCreation` as `true`) would likely be sufficient. + +Note that `FilterChainProxy` does not invoke standard filter lifecycle methods on the filters it is configured with. We recommend you use Spring's application context lifecycle interfaces as an alternative, just as you would for any other Spring bean. + +When we looked at how to set up web security using <>, we used a `DelegatingFilterProxy` with the name "springSecurityFilterChain". You should now be able to see that this is the name of the `FilterChainProxy` which is created by the namespace. + + +===== Bypassing the Filter Chain +You can use the attribute `filters = "none"` as an alternative to supplying a filter bean list. This will omit the request pattern from the security filter chain entirely. Note that anything matching this path will then have no authentication or authorization services applied and will be freely accessible. If you want to make use of the contents of the `SecurityContext` contents during a request, then it must have passed through the security filter chain. Otherwise the `SecurityContextHolder` will not have been populated and the contents will be null. + + +==== Filter Ordering +The order that filters are defined in the chain is very important. Irrespective of which filters you are actually using, the order should be as follows: + +* `ChannelProcessingFilter`, because it might need to redirect to a different protocol +* `SecurityContextPersistenceFilter`, so a `SecurityContext` can be set up in the `SecurityContextHolder` at the beginning of a web request, and any changes to the `SecurityContext` can be copied to the `HttpSession` when the web request ends (ready for use with the next web request) +* `ConcurrentSessionFilter`, because it uses the `SecurityContextHolder` functionality and needs to update the `SessionRegistry` to reflect ongoing requests from the principal +* Authentication processing mechanisms - `UsernamePasswordAuthenticationFilter`, `CasAuthenticationFilter`, `BasicAuthenticationFilter` etc - so that the `SecurityContextHolder` can be modified to contain a valid `Authentication` request token +* The `SecurityContextHolderAwareRequestFilter`, if you are using it to install a Spring Security aware `HttpServletRequestWrapper` into your servlet container +* The `JaasApiIntegrationFilter`, if a `JaasAuthenticationToken` is in the `SecurityContextHolder` this will process the `FilterChain` as the `Subject` in the `JaasAuthenticationToken` +* `RememberMeAuthenticationFilter`, so that if no earlier authentication processing mechanism updated the `SecurityContextHolder`, and the request presents a cookie that enables remember-me services to take place, a suitable remembered `Authentication` object will be put there +* `AnonymousAuthenticationFilter`, so that if no earlier authentication processing mechanism updated the `SecurityContextHolder`, an anonymous `Authentication` object will be put there +* `ExceptionTranslationFilter`, to catch any Spring Security exceptions so that either an HTTP error response can be returned or an appropriate `AuthenticationEntryPoint` can be launched +* `FilterSecurityInterceptor`, to protect web URIs and raise exceptions when access is denied + +[[request-matching]] +==== Request Matching and HttpFirewall +Spring Security has several areas where patterns you have defined are tested against incoming requests in order to decide how the request should be handled. This occurs when the `FilterChainProxy` decides which filter chain a request should be passed through and also when the `FilterSecurityInterceptor` decides which security constraints apply to a request. It's important to understand what the mechanism is and what URL value is used when testing against the patterns that you define. + +The Servlet Specification defines several properties for the `HttpServletRequest` which are accessible via getter methods, and which we might want to match against. These are the `contextPath`, `servletPath`, `pathInfo` and `queryString`. Spring Security is only interested in securing paths within the application, so the `contextPath` is ignored. Unfortunately, the servlet spec does not define exactly what the values of `servletPath` and `pathInfo` will contain for a particular request URI. For example, each path segment of a URL may contain parameters, as defined in http://www.ietf.org/rfc/rfc2396.txt[RFC 2396] footnote:[You have probably seen this when a browser doesn't support cookies and the `jsessionid` parameter is appended to the URL after a semi-colon. However the RFC allows the presence of these parameters in any path segment of the URL]. The Specification does not clearly state whether these should be included in the `servletPath` and `pathInfo` values and the behaviour varies between different servlet containers. There is a danger that when an application is deployed in a container which does not strip path parameters from these values, an attacker could add them to the requested URL in order to cause a pattern match to succeed or fail unexpectedly. footnote:[The original values will be returned once the request leaves the `FilterChainProxy`, so will still be available to the application.]. Other variations in the incoming URL are also possible. For example, it could contain path-traversal sequences (like `/../`) or multiple forward slashes (`//`) which could also cause pattern-matches to fail. Some containers normalize these out before performing the servlet mapping, but others don't. To protect against issues like these, `FilterChainProxy` uses an `HttpFirewall` strategy to check and wrap the request. Un-normalized requests are automatically rejected by default, and path parameters and duplicate slashes are removed for matching purposes. footnote:[So, for example, an original request path `/secure;hack=1/somefile.html;hack=2` will be returned as `/secure/somefile.html`.]. It is therefore essential that a `FilterChainProxy` is used to manage the security filter chain. Note that the `servletPath` and `pathInfo` values are decoded by the container, so your application should not have any valid paths which contain semi-colons, as these parts will be removed for matching purposes. + +As mentioned above, the default strategy is to use Ant-style paths for matching and this is likely to be the best choice for most users. The strategy is implemented in the class `AntPathRequestMatcher` which uses Spring's `AntPathMatcher` to perform a case-insensitive match of the pattern against the concatenated `servletPath` and `pathInfo`, ignoring the `queryString`. + +If for some reason, you need a more powerful matching strategy, you can use regular expressions. The strategy implementation is then`RegexRequestMatcher`. See the Javadoc for this class for more information. + +In practice we recommend that you use method security at your service layer, to control access to your application, and do not rely entirely on the use of security constraints defined at the web-application level. URLs change and it is difficult to take account of all the possible URLs that an application might support and how requests might be manipulated. You should try and restrict yourself to using a few simple ant paths which are simple to understand. Always try to use a"deny-by-default" approach where you have a catch-all wildcard ( `/**` or `**`) defined last and denying access. + +Security defined at the service layer is much more robust and harder to bypass, so you should always take advantage of Spring Security's method security options. + + +==== Use with other Filter-Based Frameworks +If you're using some other framework that is also filter-based, then you need to make sure that the Spring Security filters come first. This enables the `SecurityContextHolder` to be populated in time for use by the other filters. Examples are the use of SiteMesh to decorate your web pages or a web framework like Wicket which uses a filter to handle its requests. + + +[[filter-chains-with-ns]] +==== Advanced Namespace Configuration +As we saw earlier in the namespace chapter, it's possible to use multiple `http` elements to define different security configurations for different URL patterns. Each element creates a filter chain within the internal `FilterChainProxy` and the URL pattern that should be mapped to it. The elements will be added in the order they are declared, so the most specific patterns must again be declared first. Here's another example, for a similar situation to that above, where the application supports both a stateless RESTful API and also a normal web application which users log into using a form. + + +[source,xml] +---- + + + + + + + + + + + + + + + +---- + +[[core-web-filters]] +=== Core Security Filters +There are some key filters which will always be used in a web application which uses Spring Security, so we'll look at these and their supporting classes and interfaces first. We won't cover every feature, so be sure to look at the Javadoc for them if you want to get the complete picture. + +[[filter-security-interceptor]] +==== FilterSecurityInterceptor +We've already seen `FilterSecurityInterceptor` briefly when discussing <>, and we've already used it with the namespace where the `` elements are combined to configure it internally. Now we'll see how to explicitly configure it for use with a`FilterChainProxy`, along with its companion filter `ExceptionTranslationFilter`. A typical configuration example is shown below: + +[source,xml] +---- + + + + + + + + + + +---- + +`FilterSecurityInterceptor` is responsible for handling the security of HTTP resources. It requires a reference to an `AuthenticationManager` and an `AccessDecisionManager`. It is also supplied with configuration attributes that apply to different HTTP URL requests. Refer back to <> in the technical introduction. + +The `FilterSecurityInterceptor` can be configured with configuration attributes in two ways. The first, which is shown above, is using the `` namespace element. This is similar to the `` element from the namespace chapter but the `` child elements only use the `pattern` and `access` attributes. Commas are used to delimit the different configuration attributes that apply to each HTTP URL. The second option is to write your own`SecurityMetadataSource`, but this is beyond the scope of this document. Irrespective of the approach used, the `SecurityMetadataSource` is responsible for returning a `List` containing all of the configuration attributes associated with a single secure HTTP URL. + +It should be noted that the `FilterSecurityInterceptor.setSecurityMetadataSource()` method actually expects an instance of `FilterInvocationSecurityMetadataSource`. This is a marker interface which subclasses`SecurityMetadataSource`. It simply denotes the `SecurityMetadataSource` understands `FilterInvocation` s. In the interests of simplicity we'll continue to refer to the `FilterInvocationSecurityMetadataSource` as a `SecurityMetadataSource`, as the distinction is of little relevance to most users. + +The `SecurityMetadataSource` created by the namespace syntax obtains the configuration attributes for a particular `FilterInvocation` by matching the request URL against the configured `pattern` attributes. This behaves in the same way as it does for namespace configuration. The default is to treat all expressions as Apache Ant paths and regular expressions are also supported for more complex cases. The `path-type` attribute is used to specify the type of pattern being used. It is not possible to mix expression syntaxes within the same definition. As an example, the previous configuration using regular expressions instead of Ant paths would be written as follows: + +[source,xml] +---- + + + + + + + + + + + +---- + +Patterns are always evaluated in the order they are defined. Thus it is important that more specific patterns are defined higher in the list than less specific patterns. This is reflected in our example above, where the more specific `/secure/super/` pattern appears higher than the less specific `/secure/` pattern. If they were reversed, the `/secure/` pattern would always match and the `/secure/super/` pattern would never be evaluated. + +[[exception-translation-filter]] +==== ExceptionTranslationFilter +The `ExceptionTranslationFilter` sits above the `FilterSecurityInterceptor` in the security filter stack. It doesn't do any actual security enforcement itself, but handles exceptions thrown by the security interceptors and provides suitable and HTTP responses. + +[source,xml] +---- + + + + + + + + + + + + + + +---- + +[[auth-entry-point]] +===== AuthenticationEntryPoint +The `AuthenticationEntryPoint` will be called if the user requests a secure HTTP resource but they are not authenticated. An appropriate `AuthenticationException` or `AccessDeniedException` will be thrown by a security interceptor further down the call stack, triggering the `commence` method on the entry point. This does the job of presenting the appropriate response to the user so that authentication can begin. The one we've used here is `LoginUrlAuthenticationEntryPoint`, which redirects the request to a different URL (typically a login page). The actual implementation used will depend on the authentication mechanism you want to be used in your application. + + +[[access-denied-handler]] +===== AccessDeniedHandler +What happens if a user is already authenticated and they try to access a protected resource? In normal usage, this shouldn't happen because the application workflow should be restricted to operations to which a user has access. For example, an HTML link to an administration page might be hidden from users who do not have an admin role. You can't rely on hiding links for security though, as there's always a possibility that a user will just enter the URL directly in an attempt to bypass the restrictions. Or they might modify a RESTful URL to change some of the argument values. Your application must be protected against these scenarios or it will definitely be insecure. You will typically use simple web layer security to apply constraints to basic URLs and use more specific method-based security on your service layer interfaces to really nail down what is permissible. + +If an `AccessDeniedException` is thrown and a user has already been authenticated, then this means that an operation has been attempted for which they don't have enough permissions. In this case, `ExceptionTranslationFilter` will invoke a second strategy, the `AccessDeniedHandler`. By default, an `AccessDeniedHandlerImpl` is used, which just sends a 403 (Forbidden) response to the client. Alternatively you can configure an instance explicitly (as in the above example) and set an error page URL which it will forwards the request to footnote:[ +We use a forward so that the SecurityContextHolder still contains details of the principal, which may be useful for displaying to the user. In old releases of Spring Security we relied upon the servlet container to handle a 403 error message, which lacked this useful contextual information. +]. This can be a simple "access denied" page, such as a JSP, or it could be a more complex handler such as an MVC controller. And of course, you can implement the interface yourself and use your own implementation. + +It's also possible to supply a custom `AccessDeniedHandler` when you're using the namespace to configure your application. See <> for more details. + + +[[request-caching]] +===== SavedRequest s and the RequestCache Interface +Another of `ExceptionTranslationFilter`'s responsibilities is to save the current request before invoking the `AuthenticationEntryPoint`. This allows the request to be restored after the use has authenticated (see previous overview of <>). A typical example would be where the user logs in with a form, and is then redirected to the original URL by the default `SavedRequestAwareAuthenticationSuccessHandler` (see <>). + +The `RequestCache` encapsulates the functionality required for storing and retrieving `HttpServletRequest` instances. By default the `HttpSessionRequestCache` is used, which stores the request in the `HttpSession`. The `RequestCacheFilter` has the job of actually restoring the saved request from the cache when the user is redirected to the original URL. + +Under normal circumstances, you shouldn't need to modify any of this functionality, but the saved-request handling is a "best-effort" approach and there may be situations which the default configuration isn't able to handle. The use of these interfaces makes it fully pluggable from Spring Security 3.0 onwards. + + +[[security-context-persistence-filter]] +==== SecurityContextPersistenceFilter +We covered the purpose of this all-important filter in the <> chapter so you might want to re-read that section at this point. Let's first take a look at how you would configure it for use with a `FilterChainProxy`. A basic configuration only requires the bean itself + +[source,xml] +---- + +---- + +As we saw previously, this filter has two main tasks. It is responsible for storage of the `SecurityContext` contents between HTTP requests and for clearing the `SecurityContextHolder` when a request is completed. Clearing the `ThreadLocal` in which the context is stored is essential, as it might otherwise be possible for a thread to be replaced into the servlet container's thread pool, with the security context for a particular user still attached. This thread might then be used at a later stage, performing operations with the wrong credentials. + + +[[security-context-repository]] +===== SecurityContextRepository +From Spring Security 3.0, the job of loading and storing the security context is now delegated to a separate strategy interface: + +[source,java] +---- +public interface SecurityContextRepository { + + SecurityContext loadContext(HttpRequestResponseHolder requestResponseHolder); + + void saveContext(SecurityContext context, HttpServletRequest request, + HttpServletResponse response); +} +---- + +The `HttpRequestResponseHolder` is simply a container for the incoming request and response objects, allowing the implementation to replace these with wrapper classes. The returned contents will be passed to the filter chain. + +The default implementation is `HttpSessionSecurityContextRepository`, which stores the security context as an `HttpSession` attribute footnote:[In Spring Security 2.0 and earlier, this filter was called `HttpSessionContextIntegrationFilter` and performed all the work of storing the context was performed by the filter itself. If you were familiar with this class, then most of the configuration options which were available can now be found on`HttpSessionSecurityContextRepository`.]. The most important configuration parameter for this implementation is the `allowSessionCreation` property, which defaults to `true`, thus allowing the class to create a session if it needs one to store the security context for an authenticated user (it won't create one unless authentication has taken place and the contents of the security context have changed). If you don't want a session to be created, then you can set this property to `false`: + +[source,xml] +---- + + + + + + + +---- + +Alternatively you could provide an instance of `NullSecurityContextRepository`, a "http://en.wikipedia.org/wiki/Null_Object_pattern[null object]" implementation, which will prevent the security context from being stored, even if a session has already been created during the request. + + +[[form-login-filter]] +==== UsernamePasswordAuthenticationFilter +We've now seen the three main filters which are always present in a Spring Security web configuration. These are also the three which are automatically created by the namespace `` element and cannot be substituted with alternatives. The only thing that's missing now is an actual authentication mechanism, something that will allow a user to authenticate. This filter is the most commonly used authentication filter and the one that is most often customized footnote:[For historical reasons, prior to Spring Security 3.0, this filter was called `AuthenticationProcessingFilter` and the entry point was called `AuthenticationProcessingFilterEntryPoint`. Since the framework now supports many different forms of authentication, they have both been given more specific names in 3.0.]. It also provides the implementation used by the `` element from the namespace. There are three stages required to configure it. + +* Configure a `LoginUrlAuthenticationEntryPoint` with the URL of the login page, just as we did above, and set it on the `ExceptionTranslationFilter`. +* Implement the login page (using a JSP or MVC controller). +* Configure an instance of `UsernamePasswordAuthenticationFilter` in the application context +* Add the filter bean to your filter chain proxy (making sure you pay attention to the order). + +The login form simply contains `j_username` and `j_password` input fields, and posts to the URL that is monitored by the filter (by default this is `/j_spring_security_check`). The basic filter configuration looks something like this: + +[source,xml] +---- + + + + +---- + +[[form-login-flow-handling]] +===== Application Flow on Authentication Success and Failure +The filter calls the configured `AuthenticationManager` to process each authentication request. The destination following a successful authentication or an authentication failure is controlled by the `AuthenticationSuccessHandler` and `AuthenticationFailureHandler` strategy interfaces, respectively. The filter has properties which allow you to set these so you can customize the behaviour completely footnote:[In versions prior to 3.0, the application flow at this point had evolved to a stage was controlled by a mix of properties on this class and strategy plugins. The decision was made for 3.0 to refactor the code to make these two strategies entirely responsible.]. Some standard implementations are supplied such as `SimpleUrlAuthenticationSuccessHandler`, `SavedRequestAwareAuthenticationSuccessHandler`, `SimpleUrlAuthenticationFailureHandler` and `ExceptionMappingAuthenticationFailureHandler`. Have a look at the Javadoc for these classes and also for `AbstractAuthenticationProcessingFilter` to get an overview of how they work and the supported features. + +If authentication is successful, the resulting `Authentication` object will be placed into the `SecurityContextHolder`. The configured `AuthenticationSuccessHandler` will then be called to either redirect or forward the user to the appropriate destination. By default a `SavedRequestAwareAuthenticationSuccessHandler` is used, which means that the user will be redirected to the original destination they requested before they were asked to login. + +[NOTE] +==== +The `ExceptionTranslationFilter` caches the original request a user makes. When the user authenticates, the request handler makes use of this cached request to obtain the original URL and redirect to it. The original request is then rebuilt and used as an alternative. +==== + +If authentication fails, the configured `AuthenticationFailureHandler` will be invoked. + +[[servletapi]] +=== Servlet API integration +This section describes how Spring Security is integrated with the Servlet API. The https://github.com/SpringSource/spring-security/blob/master/samples/servletapi-xml[servletapi-xml] sample application demonstrates the usage of each of these methods. + + +[[servletapi-25]] +==== Servlet 2.5+ Integration + + +[[servletapi-remote-user]] +===== HttpServletRequest.getRemoteUser() +The http://docs.oracle.com/javaee/6/api/javax/servlet/http/HttpServletRequest.html#getRemoteUser()[HttpServletRequest.getRemoteUser()] will return the result of `SecurityContextHolder.getContext().getAuthentication().getName()` which is typically the current username. This can be useful if you want to display the current username in your application. Additionally, checking if this is null can be used to indicate if a user has authenticated or is anonymous. Knowing if the user is authenticated or not can be useful for determining if certain UI elements should be shown or not (i.e. a log out link should only be displayed if the user is authenticated). + + +[[servletapi-user-principal]] +===== HttpServletRequest.getUserPrincipal() +The http://docs.oracle.com/javaee/6/api/javax/servlet/http/HttpServletRequest.html#getUserPrincipal()[HttpServletRequest.getUserPrincipal()] will return the result of `SecurityContextHolder.getContext().getAuthentication()`. This means it is an `Authentication` which is typically an instance of `UsernamePasswordAuthenticationToken` when using username and password based authentication. This can be useful if you need additional information about your user. For example, you might have created a custom `UserDetailsService` that returns a custom `UserDetails` containing a first and last name for your user. You could obtain this information with the following: + + +[source,java] +---- +Authentication auth = httpServletRequest.getUserPrincipal(); +// assume integrated custom UserDetails called MyCustomUserDetails +// by default, typically instance of UserDetails +MyCustomUserDetails userDetails = (MyCustomUserDetails) auth.getPrincipal(); +String firstName = userDetails.getFirstName(); +String lastName = userDetails.getLastName(); +---- + +[NOTE] +==== +It should be noted that it is typically bad practice to perform so much logic throughout your application. Instead, one should centralize it to reduce any coupling of Spring Security and the Servlet API's. +==== + +[[servletapi-user-in-role]] +===== HttpServletRequest.isUserInRole(String) +The http://docs.oracle.com/javaee/6/api/javax/servlet/http/HttpServletRequest.html#isUserInRole(java.lang.String)[HttpServletRequest.isUserInRole(String)] will determine if `SecurityContextHolder.getContext().getAuthentication().getAuthorities()` contains a `GrantedAuthority` with the role passed into `isUserInRole(String)`. Typically users should not pass in the "ROLE_" prefix into this method since it is added automatically. For example, if you want to determine if the current user has the authority "ROLE_ADMIN", you could use the the following: + +[source,java] +---- +boolean isAdmin = httpServletRequest.isUserInRole("ADMIN"); +---- + +This might be useful to determine if certain UI components should be displayed. For example, you might display admin links only if the current user is an admin. + +[[servletapi-3]] +==== Servlet 3+ Integration +The following section describes the Servlet 3 methods that Spring Security integrates with. + + +[[servletapi-authenticate]] +===== HttpServletRequest.authenticate(HttpServletRequest,HttpServletResponse) +The http://docs.oracle.com/javaee/6/api/javax/servlet/http/HttpServletRequest.html#authenticate%28javax.servlet.http.HttpServletResponse%29[HttpServletRequest.authenticate(HttpServletRequest,HttpServletResponse)] method can be used to ensure that a user is authenticated. If they are not authenticated, the configured AuthenticationEntryPoint will be used to request the user to authenticate (i.e. redirect to the login page). + + +[[servletapi-login]] +===== HttpServletRequest.login(String,String) +The http://docs.oracle.com/javaee/6/api/javax/servlet/http/HttpServletRequest.html#login%28java.lang.String,%20java.lang.String%29[HttpServletRequest.login(String,String)] method can be used to authenticate the user with the current `AuthenticationManager`. For example, the following would attempt to authenticate with the username "user" and password "password": + +[source,java] +---- +try { + httpServletRequest.login("user","password"); +} catch(ServletException e) { + // fail to authenticate +} +---- + +[NOTE] +==== +It is not necessary to catch the ServletException if you want Spring Security to process the failed authentication attempt. +==== + +[[servletapi-logout]] +===== HttpServletRequest.logout() +The http://docs.oracle.com/javaee/6/api/javax/servlet/http/HttpServletRequest.html#logout%28%29[HttpServletRequest.logout()] method can be used to log the current user out. + +Typically this means that the SecurityContextHolder will be cleared out, the HttpSession will be invalidated, any "Remember Me" authentication will be cleaned up, etc. However, the configured LogoutHandler implementations will vary depending on your Spring Security configuration. It is important to note that after HttpServletRequest.logout() has been invoked, you are still in charge of writing a response out. Typically this would involve a redirect to the welcome page. + +[[servletapi-start-runnable]] +===== AsyncContext.start(Runnable) +The http://docs.oracle.com/javaee/6/api/javax/servlet/AsyncContext.html#start%28java.lang.Runnable%29[AsynchContext.start(Runnable)] method that ensures your credentials will be propagated to the new Thread. Using Spring Security's concurrency support, Spring Security overrides the AsyncContext.start(Runnable) to ensure that the current SecurityContext is used when processing the Runnable. For example, the following would output the current user's Authentication: + +[source,java] +---- +final AsyncContext async = httpServletRequest.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); + } + } +}); +---- + +[[servletapi-async]] +===== Async Servlet Support +If you are using Java Based configuration, you are ready to go. If you are using XML configuration, there are a few updates that are necessary. The first step is to ensure you have updated your web.xml to use at least the 3.0 schema as shown below: + +[source,xml] +---- + + + +---- + +Next you need to ensure that your springSecurityFilterChain is setup for processing asynchronous requests. + +[source,xml] +---- + + springSecurityFilterChain + + org.springframework.web.filter.DelegatingFilterProxy + + true + + + springSecurityFilterChain + /* + REQUEST + ASYNC + +---- + +That's it! Now Spring Security will ensure that your SecurityContext is propagated on asynchronous requests too. + +So how does it work? If you are not really interested, feel free to skip the remainder of this section, otherwise read on. Most of this is built into the Servlet specification, but there is a little bit of tweaking that Spring Security does to ensure things work with asynchronous requests properly. Prior to Spring Security 3.2, the SecurityContext from the SecurityContextHolder was automatically saved as soon as the HttpServletResponse was committed. This can cause issues in a Async environment. For example, consider the following: + +[source,java] +---- +httpServletRequest.startAsync(); +new Thread("AsyncThread") { + @Override + public void run() { + try { + // Do work + TimeUnit.SECONDS.sleep(1); + + // Write to and commit the httpServletResponse + httpServletResponse.getOutputStream().flush(); + } catch (Exception e) { + e.printStackTrace(); + } + } +}.start(); +---- + +The issue is that this Thread is not known to Spring Security, so the SecurityContext is not propagated to it. This means when we commit the HttpServletResponse there is no SecuriytContext. When Spring Security automatically saved the SecurityContext on committing the HttpServletResponse it would lose our logged in user. + +Since version 3.2, Spring Security is smart enough to no longer automatically save the SecurityContext on commiting the HttpServletResponse as soon as HttpServletRequest.startAsync() is invoked. + +[[servletapi-31]] +==== Servlet 3.1+ Integration +The following section describes the Servlet 3.1 methods that Spring Security integrates with. + +[[servletapi-change-session-id]] +===== HttpServletRequest#changeSessionId() +The http://docs.oracle.com/javaee/7/api/javax/servlet/http/HttpServletRequest.html#changeSessionId()[HttpServletRequest.changeSessionId()] is the default method for protecting against <> attacks in Servlet 3.1 and higher. + +[[basic]] +=== Basic and Digest Authentication +Basic and digest authentiation are alternative authentication mechanisms which are popular in web applications. Basic authentication is often used with stateless clients which pass their credentials on each request. It's quite common to use it in combination with form-based authentication where an application is used through both a browser-based user interface and as a web-service. However, basic authentication transmits the password as plain text so it should only really be used over an encrypted transport layer such as HTTPS. + +[[basic-processing-filter]] +==== BasicAuthenticationFilter +`BasicAuthenticationFilter` is responsible for processing basic authentication credentials presented in HTTP headers. This can be used for authenticating calls made by Spring remoting protocols (such as Hessian and Burlap), as well as normal browser user agents (such as Firefox and Internet Explorer). The standard governing HTTP Basic Authentication is defined by RFC 1945, Section 11, and `BasicAuthenticationFilter` conforms with this RFC. Basic Authentication is an attractive approach to authentication, because it is very widely deployed in user agents and implementation is extremely simple (it's just a Base64 encoding of the username:password, specified in an HTTP header). + +[[basic-config]] +===== Configuration +To implement HTTP Basic Authentication, you need to add a `BasicAuthenticationFilter` to your filter chain. The application context should contain `BasicAuthenticationFilter` and its required collaborator: + + +[source,xml] +---- + + + + + + + + +---- + +The configured `AuthenticationManager` processes each authentication request. If authentication fails, the configured `AuthenticationEntryPoint` will be used to retry the authentication process. Usually you will use the filter in combination with a`BasicAuthenticationEntryPoint`, which returns a 401 response with a suitable header to retry HTTP Basic authentication. If authentication is successful, the resulting `Authentication` object will be placed into the `SecurityContextHolder` as usual. + +If the authentication event was successful, or authentication was not attempted because the HTTP header did not contain a supported authentication request, the filter chain will continue as normal. The only time the filter chain will be interrupted is if authentication fails and the `AuthenticationEntryPoint` is called. + +[[digest-processing-filter]] +==== DigestAuthenticationFilter +`DigestAuthenticationFilter` is capable of processing digest authentication credentials presented in HTTP headers. Digest Authentication attempts to solve many of the weaknesses of Basic authentication, specifically by ensuring credentials are never sent in clear text across the wire. Many user agents support Digest Authentication, including FireFox and Internet Explorer. The standard governing HTTP Digest Authentication is defined by RFC 2617, which updates an earlier version of the Digest Authentication standard prescribed by RFC 2069. Most user agents implement RFC 2617. Spring Security's `DigestAuthenticationFilter` is compatible with the "`auth`" quality of protection (`qop`) prescribed by RFC 2617, which also provides backward compatibility with RFC 2069. Digest Authentication is a more attractive option if you need to use unencrypted HTTP (i.e. no TLS/HTTPS) and wish to maximise security of the authentication process. Indeed Digest Authentication is a mandatory requirement for the WebDAV protocol, as noted by RFC 2518 Section 17.1. + +Digest Authentication is definitely the most secure choice between Form Authentication, Basic Authentication and Digest Authentication, although extra security also means more complex user agent implementations. Central to Digest Authentication is a "nonce". This is a value the server generates. Spring Security's nonce adopts the following format: + +[source,txt] +---- +base64(expirationTime + ":" + md5Hex(expirationTime + ":" + key)) +expirationTime: The date and time when the nonce expires, expressed in milliseconds +key: A private key to prevent modification of the nonce token +---- + +The `DigestAuthenticatonEntryPoint` has a property specifying the `key` used for generating the nonce tokens, along with a `nonceValiditySeconds` property for determining the expiration time (default 300, which equals five minutes). Whist ever the nonce is valid, the digest is computed by concatenating various strings including the username, password, nonce, URI being requested, a client-generated nonce (merely a random value which the user agent generates each request), the realm name etc, then performing an MD5 hash. Both the server and user agent perform this digest computation, resulting in different hash codes if they disagree on an included value (eg password). In Spring Security implementation, if the server-generated nonce has merely expired (but the digest was otherwise valid), the `DigestAuthenticationEntryPoint` will send a `"stale=true"` header. This tells the user agent there is no need to disturb the user (as the password and username etc is correct), but simply to try again using a new nonce. + +An appropriate value for `DigestAuthenticationEntryPoint`'s `nonceValiditySeconds` parameter will depend on your application. Extremely secure applications should note that an intercepted authentication header can be used to impersonate the principal until the `expirationTime` contained in the nonce is reached. This is the key principle when selecting an appropriate setting, but it would be unusual for immensely secure applications to not be running over TLS/HTTPS in the first instance. + +Because of the more complex implementation of Digest Authentication, there are often user agent issues. For example, Internet Explorer fails to present an "`opaque`" token on subsequent requests in the same session. Spring Security filters therefore encapsulate all state information into the "`nonce`" token instead. In our testing, Spring Security's implementation works reliably with FireFox and Internet Explorer, correctly handling nonce timeouts etc. + + +[[digest-config]] +===== Configuration +Now that we've reviewed the theory, let's see how to use it. To implement HTTP Digest Authentication, it is necessary to define `DigestAuthenticationFilter` in the filter chain. The application context will need to define the `DigestAuthenticationFilter` and its required collaborators: + +[source,xml] +---- + + + + + + + + + + + +---- + +The configured `UserDetailsService` is needed because `DigestAuthenticationFilter` must have direct access to the clear text password of a user. Digest Authentication will NOT work if you are using encoded passwords in your DAO footnote:[It is possible to encode the password in the format HEX( MD5(username:realm:password) ) provided the `DigestAuthenticationFilter.passwordAlreadyEncoded` is set to `true`. However, other password encodings will not work with digest authentication.]. The DAO collaborator, along with the `UserCache`, are typically shared directly with a `DaoAuthenticationProvider`. The `authenticationEntryPoint` property must be `DigestAuthenticationEntryPoint`, so that `DigestAuthenticationFilter` can obtain the correct `realmName` and `key` for digest calculations. + +Like `BasicAuthenticationFilter`, if authentication is successful an `Authentication` request token will be placed into the `SecurityContextHolder`. If the authentication event was successful, or authentication was not attempted because the HTTP header did not contain a Digest Authentication request, the filter chain will continue as normal. The only time the filter chain will be interrupted is if authentication fails and the `AuthenticationEntryPoint` is called, as discussed in the previous paragraph. + +Digest Authentication's RFC offers a range of additional features to further increase security. For example, the nonce can be changed on every request. Despite this, Spring Security implementation was designed to minimise the complexity of the implementation (and the doubtless user agent incompatibilities that would emerge), and avoid needing to store server-side state. You are invited to review RFC 2617 if you wish to explore these features in more detail. As far as we are aware, Spring Security's implementation does comply with the minimum standards of this RFC. + + +[[remember-me]] +=== Remember-Me Authentication + + +[[remember-me-overview]] +==== Overview +Remember-me or persistent-login authentication refers to web sites being able to remember the identity of a principal between sessions. This is typically accomplished by sending a cookie to the browser, with the cookie being detected during future sessions and causing automated login to take place. Spring Security provides the necessary hooks for these operations to take place, and has two concrete remember-me implementations. One uses hashing to preserve the security of cookie-based tokens and the other uses a database or other persistent storage mechanism to store the generated tokens. + +Note that both implemementations require a `UserDetailsService`. If you are using an authentication provider which doesn't use a `UserDetailsService` (for example, the LDAP provider) then it won't work unless you also have a `UserDetailsService` bean in your application context. + + +[[remember-me-hash-token]] +==== Simple Hash-Based Token Approach +This approach uses hashing to achieve a useful remember-me strategy. In essence a cookie is sent to the browser upon successful interactive authentication, with the cookie being composed as follows: + +[source,txt] +---- +base64(username + ":" + expirationTime + ":" + +md5Hex(username + ":" + expirationTime + ":" password + ":" + key)) + +username: As identifiable to the `UserDetailsService` +password: That matches the one in the retrieved UserDetails +expirationTime: The date and time when the remember-me token expires, expressed in milliseconds +key: A private key to prevent modification of the remember-me token +---- + +As such the remember-me token is valid only for the period specified, and provided that the username, password and key does not change. Notably, this has a potential security issue in that a captured remember-me token will be usable from any user agent until such time as the token expires. This is the same issue as with digest authentication. If a principal is aware a token has been captured, they can easily change their password and immediately invalidate all remember-me tokens on issue. If more significant security is needed you should use the approach described in the next section. Alternatively remember-me services should simply not be used at all. + +If you are familiar with the topics discussed in the chapter on <>, you can enable remember-me authentication just by adding the `` element: + +[source,xml] +---- + + ... + + +---- + +The `UserDetailsService` will normally be selected automatically. If you have more than one in your application context, you need to specify which one should be used with the `user-service-ref` attribute, where the value is the name of your `UserDetailsService` bean. + +[[remember-me-persistent-token]] +==== Persistent Token Approach +This approach is based on the article http://jaspan.com/improved_persistent_login_cookie_best_practice[http://jaspan.com/improved_persistent_login_cookie_best_practice] with some minor modifications footnote:[Essentially, the username is not included in the cookie, to prevent exposing a valid login name unecessarily. There is a discussion on this in the comments section of this article.]. To use the this approach with namespace configuration, you would supply a datasource reference: + +[source,xml] +---- + + ... + + +---- + +The database should contain a `persistent_logins` table, created using the following SQL (or equivalent): + +[source,ddl] +---- +create table persistent_logins (username varchar(64) not null, + series varchar(64) primary key, + token varchar(64) not null, + last_used timestamp not null) +---- + +[[remember-me-impls]] +==== Remember-Me Interfaces and Implementations +Remember-me authentication is not used with basic authentication, given it is often not used with `HttpSession` s. Remember-me is used with `UsernamePasswordAuthenticationFilter`, and is implemented via hooks in the `AbstractAuthenticationProcessingFilter` superclass. The hooks will invoke a concrete `RememberMeServices` at the appropriate times. The interface looks like this: + +[source,java] +---- +Authentication autoLogin(HttpServletRequest request, HttpServletResponse response); + +void loginFail(HttpServletRequest request, HttpServletResponse response); + +void loginSuccess(HttpServletRequest request, HttpServletResponse response, + Authentication successfulAuthentication); +---- + +Please refer to the JavaDocs for a fuller discussion on what the methods do, although note at this stage that `AbstractAuthenticationProcessingFilter` only calls the `loginFail()` and `loginSuccess()` methods. The `autoLogin()` method is called by `RememberMeAuthenticationFilter` whenever the `SecurityContextHolder` does not contain an `Authentication`. This interface therefore provides the underlying remember-me implementation with sufficient notification of authentication-related events, and delegates to the implementation whenever a candidate web request might contain a cookie and wish to be remembered. This design allows any number of remember-me implementation strategies. We've seen above that Spring Security provides two implementations. We'll look at these in turn. + +===== TokenBasedRememberMeServices +This implementation supports the simpler approach described in <>. `TokenBasedRememberMeServices` generates a `RememberMeAuthenticationToken`, which is processed by `RememberMeAuthenticationProvider`. A `key` is shared between this authentication provider and the `TokenBasedRememberMeServices`. In addition, `TokenBasedRememberMeServices` requires A UserDetailsService from which it can retrieve the username and password for signature comparison purposes, and generate the `RememberMeAuthenticationToken` to contain the correct `GrantedAuthority` s. Some sort of logout command should be provided by the application that invalidates the cookie if the user requests this. `TokenBasedRememberMeServices` also implements Spring Security's `LogoutHandler` interface so can be used with `LogoutFilter` to have the cookie cleared automatically. + +The beans required in an application context to enable remember-me services are as follows: + +[source,xml] +---- + + + + + + + + + + + + + +---- + +Don't forget to add your `RememberMeServices` implementation to your `UsernamePasswordAuthenticationFilter.setRememberMeServices()` property, include the `RememberMeAuthenticationProvider` in your `AuthenticationManager.setProviders()` list, and add `RememberMeAuthenticationFilter` into your `FilterChainProxy` (typically immediately after your `UsernamePasswordAuthenticationFilter`). + + +===== PersistentTokenBasedRememberMeServices +This class can be used in the same way as `TokenBasedRememberMeServices`, but it additionally needs to be configured with a `PersistentTokenRepository` to store the tokens. There are two standard implementations. + +* `InMemoryTokenRepositoryImpl` which is intended for testing only. +* `JdbcTokenRepositoryImpl` which stores the tokens in a database. + +The database schema is described above in <>. + +[[csrf]] +=== Cross Site Request Forgery (CSRF) +This section discusses Spring Security's http://en.wikipedia.org/wiki/Cross-site_request_forgery[ Cross Site Request Forgery (CSRF)] support. + + +==== CSRF Attacks +Before we discuss how Spring Security can protect applications from CSRF attacks, we will explain what a CSRF attack is. Let's take a look at a concrete example to get a better understanding. + +Assume that your bank's website provides a form that allows transferring money from the currently logged in user to another bank account. For example, the HTTP request might look like: + + +[source] +---- +POST /transfer HTTP/1.1 +Host: bank.example.com +Cookie: JSESSIONID=randomid; Domain=bank.example.com; Secure; HttpOnly +Content-Type: application/x-www-form-urlencoded + +amount=100.00&routingNumber=1234&account=9876 +---- + +Now pretend you authenticate to your bank's website and then, without logging out, visit an evil website. The evil website contains an HTML page with the following form: + +[source,xml] +---- +

+ + + + +
+---- + +You like to win money, so you click on the submit button. In the process, you have unintentionally transferred $100 to a malicious user. This happens because, while the evil website cannot see your cookies, the cookies associated with your bank are still sent along with the request. + +Worst yet, this whole process could have been automated using JavaScript. This means you didn't even need to click on the button. So how do we protect ourselves from such attacks? + +==== Synchronizer Token Pattern +The issue is that the HTTP request from the bank's website and the request from the evil website are exactly the same. This means there is no way to reject requests coming from the evil website and allow requests coming from the bank's website. To protect against CSRF attacks we need to ensure there is something in the request that the evil site is unable to provide. + +One solution is to use the https://www.owasp.org/index.php/Cross-Site_Request_Forgery_(CSRF)_Prevention_Cheat_Sheet#General_Recommendation:_Synchronizer_Token_Pattern[Synchronizer Token Pattern]. This solution is to ensure that each request requires, in addition to our session cookie, a randomly generated token as an HTTP parameter. When a request is submitted, the server must look up the expected value for the parameter and compare it against the actual value in the request. If the values do not match, the request should fail. + +We can relax the expectations to only require the token for each HTTP request that updates state. This can be safely done since the same origin policy ensures the evil site cannot read the response. Additionally, we do not want to include the random token in HTTP GET as this can cause the tokens to be leaked. + +Let's take a look at how our example would change. Assume the randomly generated token is present in an HTTP parameter named _csrf. For example, the request to transfer money would look like this: + + +[source] +---- +POST /transfer HTTP/1.1 +Host: bank.example.com +Cookie: JSESSIONID=randomid; Domain=bank.example.com; Secure; HttpOnly +Content-Type: application/x-www-form-urlencoded + +amount=100.00&routingNumber=1234&account=9876&_csrf= +---- + + +You will notice that we added the _csrf parameter with a random value. Now the evil website will not be able to guess the correct value for the _csrf parameter (which must be explicitly provided on the evil website) and the transfer will fail when the server compares the actual token to the expected token. + + +==== When to use CSRF protection +When you use CSRF protection? Our recommendation is to use CSRF protection for any request that could be processed by a browser by normal users. If you are only creating a service that is used by non-browser clients, you will likely want to disable CSRF protection. + + +===== CSRF protection and JSON +A common question is, but do I need to protect JSON requests made by javascript? The short answer is, it depends. However, you must be very careful as there are CSRF exploits that can impact JSON requests. For example, a malicious user can create ahttp://blog.opensecurityresearch.com/2012/02/json-csrf-with-parameter-padding.html[CSRF with JSON using the following form]: + + +[source,xml] +---- +
+ + +
+---- + + +This will produce the following JSON structure + + +[source,javascript] +---- +{ "amount": 100, + "routingNumber": "evilsRoutingNumber", + "account": "evilsAccountNumber", + "ignore_me": "=test" +} +---- + +If an application were not validating the Content-Type, then it would be exposed to this exploit. Depending on the setup, a Spring MVC application that validates the Content-Type could still be exploited by updating the URL suffix to end with ".json" as shown below: + +[source,xml] +---- +
+ + +
+---- + +===== CSRF and Stateless Browser Applications +What if my application is stateless? That doesn't necessarily mean you are protected. In fact, if a user does not need to perform any actions in the web browser for a given request, they are likely still vulnerable to CSRF attacks. + +For example, consider an application uses a custom cookie that contains all the state within it for authentication instead of the JSESSIONID. When the CSRF attack is made the custom cookie will be sent with the request in the same manner that the JSESSIONID cookie was sent in our previous example. + +User's using basic authentication are also vulnerable to CSRF attacks since the browser will automatically include the username password in any requests in the same manner that the JSESSIONID cookie was sent in our previous example. + +[[csrf-using]] +==== Using Spring Security CSRF Protection +So what are the steps necessary to use Spring Security's to protect our site against CSRF attacks? The steps to using Spring Security's CSRF protection are outlined below: + +* <> +* <> +* <> + +[[csrf-use-proper-verbs]] +===== Use proper HTTP verbs +The first step to protecting against CSRF attacks is to ensure your website uses proper HTTP verbs. Specifically, before Spring Security's CSRF support can be of use, you need to be certain that your application is using PATCH, POST, PUT, and/or DELETE for anything that modifies state. + +This is not a limitation of Spring Security's support, but instead a general requirement for proper CSRF prevention. The reason is that including private information in an HTTP GET can cause the information to be leaked. Seehttp://www.w3.org/Protocols/rfc2616/rfc2616-sec15.html#sec15.1.3[RFC 2616 Section 15.1.3 Encoding Sensitive Information in URI's] for general guidance on using POST instead of GET for sensitive information. + + +[[csrf-configure]] +===== Configure CSRF Protection +The next step is to include Spring Security's CSRF protection within your application. Some frameworks handle invalid CSRF tokens by invaliding the user's session, but this causes <>. Instead by default Spring Security's CSRF protection will produce an HTTP 403 access denied. This can be customized by configuring the <> to process `InvalidCsrfTokenException` differently. + +For passivity reasons, if you are using the XML configuration, CSRF protection must be explicitly enabled using the <>> element. Refer to the <>> element's documentation for additional customizations. + +[NOTE] +==== +https://jira.springsource.org/browse/SEC-2347[SEC-2347] is logged to ensure Spring Security 4.x's XML namespace configuration will enable CSRF protection by default. +==== + +[source,xml] +---- + + + + +---- + +CSRF protection is enabled by default with Java configuration. If you would like to disable CSRF, the corresponding Java configuration can be seen below. Refer to the Javadoc of csrf() for additional customizations in how CSRF protection is configured. + +[source,java] +---- +@EnableWebSecurity +@Configuration +public class WebSecurityConfig extends + WebSecurityConfigurerAdapter { + + @Override + protected void configure(HttpSecurity http) throws Exception { + http + .csrf().disable(); + } +} +---- + +[[csrf-include-csrf-token]] +===== Include the CSRF Token + +[[csrf-include-csrf-token-form]] +====== Form Submissions +The last step is to ensure that you include the CSRF token in all PATCH, POST, PUT, and DELETE methods. This can be done using the _csrf request attribute to obtain the current CsrfToken. An example of doing this with a JSP is shown below: + + +[source,xml] +---- + +
+ + +
+---- + +[NOTE] +==== +If you are using Spring MVC tag, the `CsrfToken` is automatically included for you using the CsrfRequestDataValueProcessor. +==== + +[[csrf-include-csrf-token-ajax]] +====== Ajax and JSON Requests +If you using JSON, then it is not possible to submit the CSRF token within an HTTP parameter. Instead you can submit the token within a HTTP header. A typical pattern would be to include the CSRF token within your meta tags. An example with a JSP is shown below: + + +[source,xml] +---- + + + + + + + + +---- + +You can then include the token within all your Ajax requests. If you were using jQuery, this could be done with the following: + +[source,javascript] +---- +$(function () { + var token = $("meta[name='_csrf']").attr("content"); + var header = $("meta[name='_csrf_header']").attr("content"); + $(document).ajaxSend(function(e, xhr, options) { + xhr.setRequestHeader(header, token); + }); +}); +---- + +As a alternative to jQuery, we recommend using http://cujojs.com/[cujoJS’s] rest.js. https://github.com/cujojs/rest[rest.js] provides advanced support for working with HTTP request and responses in RESTful ways. A core capability is the ability to contextualize the HTTP client adding behavior as needed by chaining interceptors on to the client. + +[source,javascript] +---- +var client = rest.chain(csrf, { + token: $("meta[name='_csrf']").attr("content"), + name: $("meta[name='_csrf_header']").attr("content") +}); +---- + + +The configured client can be shared with any component of the application that needs to make a request to the CSRF protected resource. One significant different between rest.js and jQuery is that only requests made with the configured client will contain the CSRF token, vs jQuery where __all__ requests will include the token. The ability to scope which requests receive the token helps guard against leaking the CSRF token to a third party. Please refer to the https://github.com/cujojs/rest/tree/master/docs[rest.js reference documentation] for more information on rest.js. + + +[[csrf-caveats]] +==== CSRF Caveats +There are a few caveats when implementing CSRF. + + +[[csrf-timeouts]] +===== Timeouts +One issue is that the expected CSRF token is stored in the HttpSession, so as soon as the HttpSession expires your configured `AccessDeniedHandler` will receive a InvalidCsrfTokenException. If you are using the default `AccessDeniedHandler`, the browser will get an HTTP 403 and display a poor error message. + +[NOTE] +==== +One might ask why the expected `CsrfToken` isn't stored in a cookie. This is because there are known exploits in which headers (i.e. specify the cookies) can be set by another domain. This is the same reason Ruby on Railshttp://weblog.rubyonrails.org/2011/2/8/csrf-protection-bypass-in-ruby-on-rails/[no longer skips CSRF checks when the header X-Requested-With is present]. See http://lists.webappsec.org/pipermail/websecurity_lists.webappsec.org/2011-February/007533.html[this webappsec.org thread] for details on how to perform the exploit. Another disadvantage is that by removing the state (i.e. the timeout) you lose the ability to forcibly terminate the token if something got compromised. +==== + +A simple way to mitigate an active user experiencing a timeout is to have some JavaScript that lets the user know their session is about to expire. The user can click a button to continue and refresh the session. + +Alternatively, specifying a custom `AccessDeniedHandler` allows you to process the `InvalidCsrfTokenException` anyway you like. For an example of how to customize the `AccessDeniedHandler` refer to the provided links for both <> and https://github.com/spring-projects/spring-security/blob/3.2.0.RC1/config/src/test/groovy/org/springframework/security/config/annotation/web/configurers/NamespaceHttpAccessDeniedHandlerTests.groovy#L64[Java configuration]. + + +[[csrf-login]] +===== Logging In +In order to protect against forging log in requests the log in form should be protected against CSRF attacks too. Since the `CsrfToken` is stored in HttpSession, this means an HttpSession will be created as soon as `CsrfToken` token attribute is accessed. While this sounds bad in a RESTful / stateless architecture the reality is that state is necessary to implement practical security. Without state, we have nothing we can do if a token is compromised. Practically speaking, the CSRF token is quite small in size and should have a negligible impact on our architecture. + + +[[csrf-logout]] +===== Logging Out +Adding CSRF will update the LogoutFilter to only use HTTP POST. This ensures that log out requires a CSRF token and that a malicious user cannot forcibly log out your users. + +One approach is to use a form for log out. If you really want a link, you can use JavaScript to have the link perform a POST (i.e. maybe on a hidden form). For browsers with JavaScript that is disabled, you can optionally have the link take the user to a log out confirmation page that will perform the POST. + + +[[csrf-multipart]] +===== Multipart (file upload) +There are two options to using CSRF protection with multipart/form-data. Each option has its tradeoffs. + +* <> +* <> + +[NOTE] +==== +More information about using multipart forms with Spring can be found within the http://docs.spring.io/spring/docs/3.2.x/spring-framework-reference/html/mvc.html#mvc-multipart[17.10 Spring's multipart (file upload) support] section of the Spring reference. +==== + +[[csrf-multipartfilter]] +====== Placing MultipartFilter before Spring Security +The first option is to ensure that the `MultipartFilter` is specified before the Spring Security filter. Specifying the `MultipartFilter` after the Spring Security filter means that there is no authorization for invoking the `MultipartFilter` which means anyone can place temporary files on your server. However, only authorized users will be able to submit a File that is processed by your application. In general, this is the recommended approach because the temporary file upload should have a negligble impact on most servers. + +To ensure `MultipartFilter` is specified before the Spring Security filter with java configuration, users can override beforeSpringSecurityFilterChain as shown below: + +[source,java] +---- +public class SecurityApplicationInitializer extends AbstractSecurityWebApplicationInitializer { + + @Override + protected void beforeSpringSecurityFilterChain(ServletContext servletContext) { + insertFilters(servletContext, new MultipartFilter()); + } +} +---- + +To ensure `MultipartFilter` is specified before the Spring Security filter with XML configuration, users can ensure the element of the `MultipartFilter` is placed before the springSecurityFilterChain within the web.xml as shown below: + +[source,xml] +---- + + MultipartFilter + org.springframework.web.multipart.support.MultipartFilter + + + springSecurityFilterChain + org.springframework.web.filter.DelegatingFilterProxy + + + MultipartFilter + /* + + + springSecurityFilterChain + /* + + +---- + +[[csrf-include-csrf-token-in-action]] +====== Include CSRF token in action +If allowing unauthorized users to upload temporariy files is not acceptable, an alternative is to place the `MultipartFilter` after the Spring Security filter and include the CSRF as a query parameter in the action attribute of the form. An example with a jsp is shown below + +[source,xml] +---- +
+---- + +The disadvantage to this approach is that query parameters can be leaked. More genearlly, it is considered best practice to place sensitive data within the body or headers to ensure it is not leaked. Additional information can be found in http://www.w3.org/Protocols/rfc2616/rfc2616-sec15.html#sec15.1.3[RFC 2616 Section 15.1.3 Encoding Sensitive Information in URI's]. + +===== HiddenHttpMethodFilter +The HiddenHttpMethodFilter should be placed before the Spring Security filter. In general this is true, but it could have additional implications when protecting against CSRF attacks. + +Note that the HiddenHttpMethodFilter only overrides the HTTP method on a POST, so this is actually unlikely to cause any real problems. However, it is still best practice to ensure it is placed before Spring Security's filters. + +==== Overriding Defaults +Spring Security's goal is to provide defaults that protect your users from exploits. This does not mean that you are forced to accept all of its defaults. + +For example, you can provide a custom CsrfTokenRepository to override the way in which the `CsrfToken` is stored. + +You can also specify a custom RequestMatcher to determine which requests are protected by CSRF (i.e. perhaps you don't care if log out is exploited). In short, if Spring Security's CSRF protection doesn't behave exactly as you want it, you are able to customize the behavior. Refer to the <>> documentation for details on how to make these customizations with XML and the `CsrfConfigurer` javadoc for details on how to make these customizations when using Java configuration. + +[[headers]] +=== Security Headers +This section discusses Spring Security's support for adding various security headers to the response. + +==== Default Security Headers +Spring Security allows users to easily inject the default security headers to assist in protecting their application. The following is a list of the current __Default Security Headers__ provided by Spring Security: + +* <> +* <> +* <> +* <> +* <> + +While each of these headers are considered best practice, it should be noted that not all clients utilize the headers, so additional testing is encouraged. For passivity reasons, if you are using Spring Security's XML namespace support, you must explicitly enable the security headers. All of the default headers can be easily added using the <>> element with no child elements: + +[NOTE] +==== +https://jira.springsource.org/browse/SEC-2348[SEC-2348] is logged to ensure Spring Security 4.x's XML namespace configuration will enable Security headers by default. +==== + +[source,xml] +---- + + + + + +---- + +Alternatively, you can choose to explicitly list the headers you wish to include. For example, the following is the same the previous configuration. Removing any of the elements will remove that header from the responses. + +[source,xml] +---- + + + + + + + + + + + +---- + +If you are using Spring Security's Java configuration, all of the default security headers are added by default. They can be disabled using the Java configuration below: + +[source,java] +---- +@EnableWebSecurity +@Configuration +public class WebSecurityConfig extends + WebSecurityConfigurerAdapter { + + @Override + protected void configure(HttpSecurity http) throws Exception { + http + // ... + .headers().disable(); + } +} +---- + +As soon as you specify any headers that should be included, then only those headers will be include. For example, the following configuration will include support for <> and <> only. + +[source,java] +---- +@EnableWebSecurity +@Configuration +public class WebSecurityConfig extends + WebSecurityConfigurerAdapter { + + @Override + protected void configure(HttpSecurity http) throws Exception { + http + // ... + .headers() + .cacheControl() + .frameOptions(); + } +} +---- + +[[headers-cache-control]] +===== Cache Control +In the past Spring Security required you to provide your own cache control for your web application. This seemed reasonable at the time, but browser caches have evolved to include caches for secure connections as well. This means that a user may view an authenticated page, log out, and then a malicious user can use the browser history to view the cached page. To help mitigate this Spring Security has added cache control support which will insert the following headers into you response. + +[source] +---- +Cache-Control: no-cache, no-store, max-age=0, must-revalidate +Pragma: no-cache +Expires: 0 +---- + +Simply adding the <>> element with no child elements will automatically add Cache Control and quite a few other protections. However, if you only want cache control, you can enable this feature using Spring Security's XML namespace with the <>> element. + +[source,xml] +---- + + + + + + + +---- + +Similarly, you can enable only cache control within Java Configuration with the following: + +[source,java] +---- +@EnableWebSecurity +@Configuration +public class WebSecurityConfig extends + WebSecurityConfigurerAdapter { + + @Override + protected void configure(HttpSecurity http) throws Exception { + http + // ... + .headers() + .cacheControl(); + } +} +---- + +If you actually want to cache specific responses, your application can selectively invoke http://docs.oracle.com/javaee/6/api/javax/servlet/http/HttpServletResponse.html#setHeader(java.lang.String, java.lang.String)[HttpServletResponse.setHeader(String,String)] to override the header set by Spring Security. This is useful to ensure things like CSS, JavaScript, and images are properly cached. + +When using Spring Web MVC, this is typically done within your configuration. For example, the following configuration will ensure that the cache headers are set for all of your resources: + +[source,java] +---- +@EnableWebMvc +public class WebMvcConfiguration extends WebMvcConfigurerAdapter { + + @Override + public void addResourceHandlers(ResourceHandlerRegistry registry) { + registry + .addResourceHandler("/resources/**") + .addResourceLocations("/resources/") + .setCachePeriod(31556926); + } + + // ... +} +---- + +[[headers-content-type-options]] +===== Content Type Options +Historically browsers, including Internet Explorer, would try to guess the content type of a request using http://en.wikipedia.org/wiki/Content_sniffing[content sniffing]. This allowed browsers to improve the user experience by guessing the content type on resources that had not specified the content type. For example, if a browser encountered a JavaScript file that did not have the content type specified, it would be able to guess the content type and then execute it. + +[NOTE] +==== +There are many additional things one should do (i.e. only display the document in a distinct domain, ensure Content-Type header is set, sanitize the document, etc) when allowing content to be uploaded. However, these measures are out of the scope of what Spring Security provides. It is also important to point out when disabling content sniffing, you must specify the content type in order for things to work properly. +==== + +The problem with content sniffing is that this allowed malicious users to use polyglots (i.e. a file that is valid as multiple content types) to execute XSS attacks. For example, some sites may allow users to submit a valid postscript document to a website and view it. A malicious user might create a http://webblaze.cs.berkeley.edu/papers/barth-caballero-song.pdf[postscript document that is also a valid JavaScript file] and execute a XSS attack with it. + +Content sniffing can be disabled by adding the following header to our response: + +[source] +---- +X-Content-Type-Options: nosniff +---- + +Just as with the cache control element, the nosniff directive is added by default when using the element with no child elements. However, if you want more control over which headers are added you can use the <>> element as shown below: + +[source,xml] +---- + + + + + + + +---- + +The X-Content-Type-Options header is added by default with Spring Security Java configuration. If you want more control over the headers, you can explicitly specify the content type options with the following: + +[source,java] +---- +@EnableWebSecurity +@Configuration +public class WebSecurityConfig extends + WebSecurityConfigurerAdapter { + + @Override + protected void configure(HttpSecurity http) throws Exception { + http + // ... + .headers() + .contentTypeOptions(); + } +} +---- + +[[headers-hsts]] +===== HTTP Strict Transport Security (HSTS) +When you type in your bank's website, do you enter mybank.example.com or do you enter https://mybank.example.com[]? If you omit the https protocol, you are potentially vulnerable tohttp://en.wikipedia.org/wiki/Man-in-the-middle_attack[Man in the Middle attacks]. Even if the website performs a redirect to https://mybank.example.com a malicious user could intercept the initial HTTP request and manipulate the response (i.e. redirect to https://mibank.example.com and steal their credentials). + +Many users omit the https protocol and this is why http://tools.ietf.org/html/rfc6797[HTTP Strict Transport Security (HSTS)] was created. Once mybank.example.com is added as a http://tools.ietf.org/html/rfc6797#section-5.1[HSTS host], a browser can know ahead of time that any request to mybank.example.com should be interpreted as https://mybank.example.com. This greatly reduces the possibility of a Man in the Middle attack occurring. + +[NOTE] +==== +In accordance with http://tools.ietf.org/html/rfc6797#section-7.2[RFC6797], the HSTS header is only injected into HTTPS responses. In order for the browser to acknowledge the header, the browser must first trust the CA that signed the SSL certificate used to make the connection (not just the SSL certificate). +==== + +One way for a site to be marked as a HSTS host is to have the host preloaded into the browser. Another is to add the "Strict-Transport-Security" header to the response. For example the following would instruct the browser to treat the domain as an HSTS host for a year (there are approximately 31536000 seconds in a year): + +[source] +---- +Strict-Transport-Security: max-age=31536000 ; includeSubDomains +---- + +The optional includeSubDomains directive instructs Spring Security that subdomains (i.e. secure.mybank.example.com) should also be treated as an HSTS domain. + +As with the other headers, Spring Security adds the previous header to the response when the element is specified with no child elements. It is also automatically added when you are using Java Configuration. You can also only use HSTS headers with the <>> element as shown below: + +[source,xml] +---- + + + + + + + +---- + +Similarly, you can enable only HSTS headers with Java Configuration: + +[source,java] +---- +@EnableWebSecurity +@Configuration +public class WebSecurityConfig extends + WebSecurityConfigurerAdapter { + + @Override + protected void configure(HttpSecurity http) throws Exception { + http + // ... + .headers() + .hsts(); + } +} +---- + +[[headers-frame-options]] +===== X-Frame-Options +Allowing your website to be added to a frame can be a security issue. For example, using clever CSS styling users could be tricked into clicking on something that they were not intending (http://www.youtube.com/watch?v=3mk0RySeNsU[video demo]). For example, a user that is logged into their bank might click a button that grants access to other users. This sort of attack is known ashttp://en.wikipedia.org/wiki/Clickjacking[Clickjacking]. + +[NOTE] +==== +Another modern approach to dealing with clickjacking is using a http://www.w3.org/TR/CSP/[Content Security Policy]. Spring Security does not provide support for this as the specification is not released and it is quite a bit more complicated. However, you could use the<> feature to implement this. To stay up to date with this issue and to see how you can implement it with Spring Security refer to https://jira.springsource.org/browse/SEC-2117[SEC-2117] +==== + +There are a number ways to mitigate clickjacking attacks. For example, to protect legacy browsers from clickjacking attacks you can use https://www.owasp.org/index.php/Clickjacking_Defense_Cheat_Sheet#Best-for-now_Legacy_Browser_Frame_Breaking_Script[frame breaking code]. While not perfect, the frame breaking code is the best you can do for the legacy browsers. + +A more modern approach to address clickjacking is to use https://developer.mozilla.org/en-US/docs/HTTP/X-Frame-Options[X-Frame-Options] header: + +[source] +---- +X-Frame-Options: DENY +---- + +The X-Frame-Options response header instructs the browser to prevent any site with this header in the response from being rendered within a frame. As with the other response headers, this is automatically included when the element is specified with no child elements. You can also explicitly specify the <> element to control which headers are added to the response. + +[source,xml] +---- + + + + + + + +---- + +Similarly, you can enable only frame options within Java Configuration with the following: + +[source,java] +---- +@EnableWebSecurity +@Configuration +public class WebSecurityConfig extends + WebSecurityConfigurerAdapter { + + @Override + protected void configure(HttpSecurity http) throws Exception { + http + // ... + .headers() + .frameOptions(); + } +} +---- + +If you want to change the value for the X-Frame-Options header, then you can use a <>. + +[[headers-xss-protection]] +===== X-XSS-Protection +Some browsers have built in support for filtering out https://www.owasp.org/index.php/Testing_for_Reflected_Cross_site_scripting_(OWASP-DV-001)[reflected XSS attacks]. This is by no means full proof, but does assist in XSS protection. + +The filtering is typically enabled by default, so adding the header typically just ensures it is enabled and instructs the browser what to do when a XSS attack is detected. For example, the filter might try to change the content in the least invasive way to still render everything. At times, this type of replacement can become a http://hackademix.net/2009/11/21/ies-xss-filter-creates-xss-vulnerabilities/[XSS vulnerability in itself]. Instead, it is best to block the content rather than attempt to fix it. To do this we can add the following header: + +[source] +---- +X-XSS-Protection: 1; mode=block +---- + +This header is included by default when the element is specified with no child elements. We can explicitly state it using the <> element as shown below: + +[source,xml] +---- + + + + + + + +---- + +Similarly, you can enable only xss protection within Java Configuration with the following: + +[source,java] +---- +@EnableWebSecurity +@Configuration +public class WebSecurityConfig extends + WebSecurityConfigurerAdapter { + + @Override + protected void configure(HttpSecurity http) throws Exception { + http + // ... + .headers() + .xssProtection(); + } +} +---- + +[[headers-custom]] +==== Custom Headers +Spring Security has mechanisms to make it convenient to add the more common security headers to your application. However, it also provides hooks to enable adding custom headers. + +[[headers-static]] +===== Static Headers +There may be times you wish to inject custom security headers into your application that are not supported out of the box. For example, perhaps you wish to have early support for http://www.w3.org/TR/CSP/[Content Security Policy] in order to ensure that resources are only loaded from the same origin. Since support for Content Security Policy has not been finalized, browsers use one of two common extension headers to implement the feature. This means we will need to inject the policy twice. An example of the headers can be seen below: + +[source] +---- +X-Content-Security-Policy: default-src 'self' +X-WebKit-CSP: default-src 'self' +---- + +When using the XML namespace, these headers can be added to the response using the <>> element as shown below: + +[source,xml] +---- + + + + +
+
+ + +---- + +Similarly, the headers could be added to the response using Java Configuration as shown in the following: + +[source,java] +---- +@EnableWebSecurity +@Configuration +public class WebSecurityConfig extends + WebSecurityConfigurerAdapter { + + @Override + protected void configure(HttpSecurity http) throws Exception { + http + // ... + .headers() + .addHeaderWriter(new StaticHeaderWriter("X-Content-Security-Policy","default-src 'self'")) + .addHeaderWriter(new StaticHeaderWriter("X-WebKit-CSP","default-src 'self'")); + } +} +---- + +[[headers-writer]] +===== Headers Writer +When the namespace or Java configuration does not support the headers you want, you can create a custom `HeadersWriter` instance or even provide a custom implementation of the `HeadersWriter`. + +Let's take a look at an example of using an custom instance of `XFrameOptionsHeaderWriter`. Perhaps you want to allow framing of content for the same origin. This is easily supported by setting the <> attribute to "SAMEORIGIN", but let's take a look at a more explicit example using the <> attribute. + +[source,xml] +---- + + + + +
+ + + + +---- + + +We could also restrict framing of content to the same origin with Java configuration: + + +[source,java] +---- +@EnableWebSecurity +@Configuration +public class WebSecurityConfig extends + WebSecurityConfigurerAdapter { + + @Override + protected void configure(HttpSecurity http) throws Exception { + http + // ... + .headers() + .addHeaderWriter(new XFrameOptionsHeaderWriter(XFrameOptionsMode.SAMEORIGIN)); + } +} +---- + + + +[[headers-delegatingrequestmatcherheaderwriter]] +===== DelegatingRequestMatcherHeaderWriter +At times you may want to only write a header for certain requests. For example, perhaps you want to only protect your log in page from being framed. You could use the `DelegatingRequestMatcherHeaderWriter` to do so. When using the XML namespace configuration, this can be done with the following: + + +[source,xml] +---- + + + + +
+ + + + + + + + + + + +---- + + +We could also prevent framing of content to the log in page using java configuration: + + +[source,java] +---- +@EnableWebSecurity +@Configuration +public class WebSecurityConfig extends + WebSecurityConfigurerAdapter { + + @Override + protected void configure(HttpSecurity http) throws Exception { + RequestMatcher matcher = new AntPathRequestMatcher("/login"); + DelegatingRequestMatcherHeaderWriter headerWriter = + new DelegatingRequestMatcherHeaderWriter(matcher,new XFrameOptionsHeaderWriter()); + http + // ... + .headers() + .addHeaderWriter(headerWriter); + } +} +---- + + + +[[session-mgmt]] +=== Session Management +HTTP session related functonality is handled by a combination of the `SessionManagementFilter` and the `SessionAuthenticationStrategy` interface, which the filter delegates to. Typical usage includes session-fixation protection attack prevention, detection of session timeouts and restrictions on how many sessions an authenticated user may have open concurrently. + + +==== SessionManagementFilter +The `SessionManagementFilter` checks the contents of the `SecurityContextRepository` against the current contents of the `SecurityContextHolder` to determine whether a user has been authenticated during the current request, typically by a non-interactive authentication mechanism, such as pre-authentication or remember-me footnote:[ +Authentication by mechanisms which perform a redirect after authenticating (such as form-login) will not be detected by`SessionManagementFilter`, as the filter will not be invoked during the authenticating request. Session-management functionality has to be handled separately in these cases. +]. If the repository contains a security context, the filter does nothing. If it doesn't, and the thread-local `SecurityContext` contains a (non-anonymous) `Authentication` object, the filter assumes they have been authenticated by a previous filter in the stack. It will then invoke the configured `SessionAuthenticationStrategy`. + +If the user is not currently authenticated, the filter will check whether an invalid session ID has been requested (because of a timeout, for example) and will invoke the configured`InvalidSessionStrategy`, if one is set. The most common behaviour is just to redirect to a fixed URL and this is encapsulated in the standard implementation`SimpleRedirectInvalidSessionStrategy`. The latter is also used when configuring an invalid session URL through the namespace,<>. + + +==== SessionAuthenticationStrategy +`SessionAuthenticationStrategy` is used by both `SessionManagementFilter` and `AbstractAuthenticationProcessingFilter`, so if you are using a customized form-login class, for example, you will need to inject it into both of these. In this case, a typical configuration, combining the namespace and custom beans might look like this: + +[source,xml] +---- + + + + + + + + + ... + + + + +---- + + + Note that the use of the default, `SessionFixationProtectionStrategy` may cause issues if you are storing beans in the session which implement `HttpSessionBindingListener`, including Spring session-scoped beans. See the Javadoc for this class for more information. + + +[[concurrent-sessions]] +==== Concurrency Control +Spring Security is able to prevent a principal from concurrently authenticating to the same application more than a specified number of times. Many ISVs take advantage of this to enforce licensing, whilst network administrators like this feature because it helps prevent people from sharing login names. You can, for example, stop user"Batman" from logging onto the web application from two different sessions. You can either expire their previous login or you can report an error when they try to log in again, preventing the second login. Note that if you are using the second approach, a user who has not explicitly logged out (but who has just closed their browser, for example) will not be able to log in again until their original session expires. + +Concurrency control is supported by the namespace, so please check the earlier namespace chapter for the simplest configuration. Sometimes you need to customize things though. + +The implementation uses a specialized version of `SessionAuthenticationStrategy`, called `ConcurrentSessionControlAuthenticationStrategy`. +[NOTE] +==== + +Previously the concurrent authentication check was made by the `ProviderManager`, which could be injected with a `ConcurrentSessionController`. The latter would check if the user was attempting to exceed the number of permitted sessions. However, this approach required that an HTTP session be created in advance, which is undesirable. In Spring Security 3, the user is first authenticated by the `AuthenticationManager` and once they are successfully authenticated, a session is created and the check is made whether they are allowed to have another session open. + +==== + + +To use concurrent session support, you'll need to add the following to `web.xml`: + +[source,xml] +---- + + + + org.springframework.security.web.session.HttpSessionEventPublisher + + +---- + + + +In addition, you will need to add the `ConcurrentSessionFilter` to your `FilterChainProxy`. The `ConcurrentSessionFilter` requires two properties, `sessionRegistry`, which generally points to an instance of `SessionRegistryImpl`, and `expiredUrl`, which points to the page to display when a session has expired. A configuration using the namespace to create the `FilterChainProxy` and other default beans might look like this: + +[source,xml] +---- + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +---- + + + +Adding the listener to `web.xml` causes an `ApplicationEvent` to be published to the Spring `ApplicationContext` every time a `HttpSession` commences or terminates. This is critical, as it allows the `SessionRegistryImpl` to be notified when a session ends. Without it, a user will never be able to log back in again once they have exceeded their session allowance, even if they log out of another session or it times out. + + +[[list-authenticated-principals]] +===== Querying the SessionRegistry for currently authenticated users and their sessions +Setting up concurrency-control, either through the namespace or using plain beans has the useful side effect of providing you with a reference to the `SessionRegistry` which you can use directly within your application, so even if you don't want to restrict the number of sessions a user may have, it may be worth setting up the infrastructure anyway. You can set the `maximumSession` property to -1 to allow unlimited sessions. If you're using the namespace, you can set an alias for the internally-created `SessionRegistry` using the `session-registry-alias` attribute, providing a reference which you can inject into your own beans. + +The `getAllPrincipals()` method supplies you with a list of the currently authenticated users. You can list a user's sessions by calling the `getAllSessions(Object principal, boolean includeExpiredSessions)` method, which returns a list of `SessionInformation` objects. You can also expire a user's session by calling `expireNow()` on a `SessionInformation` instance. When the user returns to the application, they will be prevented from proceeding. You may find these methods useful in an administration application, for example. Have a look at the Javadoc for more information. + + +[[anonymous]] +=== Anonymous Authentication + + +[[anonymous-overview]] +==== Overview +It's generally considered good security practice to adopt a "deny-by-default" where you explicitly specify what is allowed and disallow everything else. Defining what is accessible to unauthenticated users is a similar situation, particularly for web applications. Many sites require that users must be authenticated for anything other than a few URLs (for example the home and login pages). In this case it is easiest to define access configuration attributes for these specific URLs rather than have for every secured resource. Put differently, sometimes it is nice to say `ROLE_SOMETHING` is required by default and only allow certain exceptions to this rule, such as for login, logout and home pages of an application. You could also omit these pages from the filter chain entirely, thus bypassing the access control checks, but this may be undesirable for other reasons, particularly if the pages behave differently for authenticated users. + +This is what we mean by anonymous authentication. Note that there is no real conceptual difference between a user who is "anonymously authenticated" and an unauthenticated user. Spring Security's anonymous authentication just gives you a more convenient way to configure your access-control attributes. Calls to servlet API calls such as `getCallerPrincipal`, for example, will still return null even though there is actually an anonymous authentication object in the `SecurityContextHolder`. + +There are other situations where anonymous authentication is useful, such as when an auditing interceptor queries the `SecurityContextHolder` to identify which principal was responsible for a given operation. Classes can be authored more robustly if they know the `SecurityContextHolder` always contains an `Authentication` object, and never `null`. + + +[[anonymous-config]] +==== Configuration +Anonymous authentication support is provided automatically when using the HTTP configuration Spring Security 3.0 and can be customized (or disabled) using the `` element. You don't need to configure the beans described here unless you are using traditional bean configuration. + +Three classes that together provide the anonymous authentication feature. `AnonymousAuthenticationToken` is an implementation of `Authentication`, and stores the `GrantedAuthority` s which apply to the anonymous principal. There is a corresponding `AnonymousAuthenticationProvider`, which is chained into the `ProviderManager` so that `AnonymousAuthenticationToken` s are accepted. Finally, there is an `AnonymousAuthenticationFilter`, which is chained after the normal authentication mechanisms and automatically adds an `AnonymousAuthenticationToken` to the `SecurityContextHolder` if there is no existing `Authentication` held there. The definition of the filter and authentication provider appears as follows: + + + +[source,xml] +---- + + + + + + + + + +---- + + + +The `key` is shared between the filter and authentication provider, so that tokens created by the former are accepted by the latter footnote:[ +The use of the `key` property should not be regarded as providing any real security here. It is merely a book-keeping exercise. If you are sharing a `ProviderManager` which contains an `AnonymousAuthenticationProvider` in a scenario where it is possible for an authenticating client to construct the `Authentication` object (such as with RMI invocations), then a malicious client could submit an `AnonymousAuthenticationToken` which it had created itself (with chosen username and authority list). If the `key` is guessable or can be found out, then the token would be accepted by the anonymous provider. This isn't a problem with normal usage but if you are using RMI you would be best to use a customized `ProviderManager` which omits the anonymous provider rather than sharing the one you use for your HTTP authentication mechanisms. +]. The `userAttribute` is expressed in the form of `usernameInTheAuthenticationToken,grantedAuthority[,grantedAuthority]`. This is the same syntax as used after the equals sign for`InMemoryDaoImpl`'s `userMap` property. + +As explained earlier, the benefit of anonymous authentication is that all URI patterns can have security applied to them. For example: + + + +[source,xml] +---- + + + + + + + + + + + + " + + + +---- + + + + +[[anonymous-auth-trust-resolver]] +==== AuthenticationTrustResolver +Rounding out the anonymous authentication discussion is the `AuthenticationTrustResolver` interface, with its corresponding `AuthenticationTrustResolverImpl` implementation. This interface provides an `isAnonymous(Authentication)` method, which allows interested classes to take into account this special type of authentication status. The `ExceptionTranslationFilter` uses this interface in processing `AccessDeniedException` s. If an `AccessDeniedException` is thrown, and the authentication is of an anonymous type, instead of throwing a 403 (forbidden) response, the filter will instead commence the `AuthenticationEntryPoint` so the principal can authenticate properly. This is a necessary distinction, otherwise principals would always be deemed "authenticated" and never be given an opportunity to login via form, basic, digest or some other normal authentication mechanism. + +You will often see the `ROLE_ANONYMOUS` attribute in the above interceptor configuration replaced with `IS_AUTHENTICATED_ANONYMOUSLY`, which is effectively the same thing when defining access controls. This is an example of the use of the `AuthenticatedVoter` which we will see in the <>. It uses an `AuthenticationTrustResolver` to process this particular configuration attribute and grant access to anonymous users. the `AuthenticatedVoter` approach is more powerful, since it allows you to differentiate between anonymous, remember-me and fully-authenticated users. If you don't need this functionality though, then you can stick with `ROLE_ANONYMOUS`, which will be processed by Spring Security's standard `RoleVoter`. + + +[[authorization]] +== Authorization +The advanced authorization capabilities within Spring Security represent one of the most compelling reasons for its popularity. Irrespective of how you choose to authenticate - whether using a Spring Security-provided mechanism and provider, or integrating with a container or other non-Spring Security authentication authority - you will find the authorization services can be used within your application in a consistent and simple way. + +In this part we'll explore the different `AbstractSecurityInterceptor` implementations, which were introduced in Part I. We then move on to explore how to fine-tune authorization through use of domain access control lists. + + +[[authz-arch]] +=== Authorization Architecture + + +[[authz-authorities]] +==== Authorities +As we saw in the <>, all `Authentication` implementations store a list of `GrantedAuthority` objects. These represent the authorities that have been granted to the principal. the `GrantedAuthority` objects are inserted into the `Authentication` object by the `AuthenticationManager` and are later read by `AccessDecisionManager` s when making authorization decisions. + +`GrantedAuthority` is an interface with only one method: + +[source,java] +---- + + String getAuthority(); + +---- + +This method allows + `AccessDecisionManager` s to obtain a precise `String` representation of the `GrantedAuthority`. By returning a representation as a `String`, a `GrantedAuthority` can be easily "read" by most `AccessDecisionManager` s. If a `GrantedAuthority` cannot be precisely represented as a `String`, the `GrantedAuthority` is considered "complex" and `getAuthority()` must return `null`. + +An example of a "complex" `GrantedAuthority` would be an implementation that stores a list of operations and authority thresholds that apply to different customer account numbers. Representing this complex `GrantedAuthority` as a `String` would be quite difficult, and as a result the `getAuthority()` method should return `null`. This will indicate to any `AccessDecisionManager` that it will need to specifically support the `GrantedAuthority` implementation in order to understand its contents. + +Spring Security includes one concrete `GrantedAuthority` implementation, `GrantedAuthorityImpl`. This allows any user-specified `String` to be converted into a `GrantedAuthority`. All `AuthenticationProvider` s included with the security architecture use `GrantedAuthorityImpl` to populate the `Authentication` object. + + +[[authz-pre-invocation]] +==== Pre-Invocation Handling +As we've also seen in the <> chapter, Spring Security provides interceptors which control access to secure objects such as method invocations or web requests. A pre-invocation decision on whether the invocation is allowed to proceed is made by the `AccessDecisionManager`. + + +[[authz-access-decision-manager]] +===== The AccessDecisionManager +The `AccessDecisionManager` is called by the `AbstractSecurityInterceptor` and is responsible for making final access control decisions. the `AccessDecisionManager` interface contains three methods: + +[source,java] +---- +void decide(Authentication authentication, Object secureObject, + Collection attrs) throws AccessDeniedException; + +boolean supports(ConfigAttribute attribute); + +boolean supports(Class clazz); +---- + +The `AccessDecisionManager`'s `decide` method is passed all the relevant information it needs in order to make an authorization decision. In particular, passing the secure `Object` enables those arguments contained in the actual secure object invocation to be inspected. For example, let's assume the secure object was a`MethodInvocation`. It would be easy to query the `MethodInvocation` for any `Customer` argument, and then implement some sort of security logic in the `AccessDecisionManager` to ensure the principal is permitted to operate on that customer. Implementations are expected to throw an `AccessDeniedException` if access is denied. + +The `supports(ConfigAttribute)` method is called by the `AbstractSecurityInterceptor` at startup time to determine if the `AccessDecisionManager` can process the passed `ConfigAttribute`. The `supports(Class)` method is called by a security interceptor implementation to ensure the configured `AccessDecisionManager` supports the type of secure object that the security interceptor will present. + +[[authz-voting-based]] +===== Voting-Based AccessDecisionManager ImplementationsVoting Decision Manager +Whilst users can implement their own `AccessDecisionManager` to control all aspects of authorization, Spring Security includes several `AccessDecisionManager` implementations that are based on voting. <> illustrates the relevant classes. + +[[authz-access-voting]] +.Voting Decision Manager +image::images/access-decision-voting.png[] + + + +Using this approach, a series of `AccessDecisionVoter` implementations are polled on an authorization decision. The `AccessDecisionManager` then decides whether or not to throw an `AccessDeniedException` based on its assessment of the votes. + +The `AccessDecisionVoter` interface has three methods: + +[source,java] +---- +int vote(Authentication authentication, Object object, Collection attrs); + +boolean supports(ConfigAttribute attribute); + +boolean supports(Class clazz); +---- + +Concrete implementations return an `int`, with possible values being reflected in the `AccessDecisionVoter` static fields `ACCESS_ABSTAIN`, `ACCESS_DENIED` and `ACCESS_GRANTED`. A voting implementation will return `ACCESS_ABSTAIN` if it has no opinion on an authorization decision. If it does have an opinion, it must return either `ACCESS_DENIED` or `ACCESS_GRANTED`. + +There are three concrete `AccessDecisionManager` s provided with Spring Security that tally the votes. the `ConsensusBased` implementation will grant or deny access based on the consensus of non-abstain votes. Properties are provided to control behavior in the event of an equality of votes or if all votes are abstain. The `AffirmativeBased` implementation will grant access if one or more `ACCESS_GRANTED` votes were received (i.e. a deny vote will be ignored, provided there was at least one grant vote). Like the `ConsensusBased` implementation, there is a parameter that controls the behavior if all voters abstain. The `UnanimousBased` provider expects unanimous `ACCESS_GRANTED` votes in order to grant access, ignoring abstains. It will deny access if there is any `ACCESS_DENIED` vote. Like the other implementations, there is a parameter that controls the behaviour if all voters abstain. + +It is possible to implement a custom `AccessDecisionManager` that tallies votes differently. For example, votes from a particular `AccessDecisionVoter` might receive additional weighting, whilst a deny vote from a particular voter may have a veto effect. + + +[[authz-role-voter]] +====== RoleVoter +The most commonly used `AccessDecisionVoter` provided with Spring Security is the simple `RoleVoter`, which treats configuration attributes as simple role names and votes to grant access if the user has been assigned that role. + +It will vote if any `ConfigAttribute` begins with the prefix `ROLE_`. It will vote to grant access if there is a `GrantedAuthority` which returns a `String` representation (via the `getAuthority()` method) exactly equal to one or more `ConfigAttributes` starting with the prefix `ROLE_`. If there is no exact match of any `ConfigAttribute` starting with `ROLE_`, the `RoleVoter` will vote to deny access. If no `ConfigAttribute` begins with `ROLE_`, the voter will abstain. + + +[[authz-authenticated-voter]] +====== AuthenticatedVoter +Another voter which we've implicitly seen is the `AuthenticatedVoter`, which can be used to differentiate between anonymous, fully-authenticated and remember-me authenticated users. Many sites allow certain limited access under remember-me authentication, but require a user to confirm their identity by logging in for full access. + +When we've used the attribute `IS_AUTHENTICATED_ANONYMOUSLY` to grant anonymous access, this attribute was being processed by the `AuthenticatedVoter`. See the Javadoc for this class for more information. + + +[[authz-custom-voter]] +====== Custom Voters +Obviously, you can also implement a custom `AccessDecisionVoter` and you can put just about any access-control logic you want in it. It might be specific to your application (business-logic related) or it might implement some security administration logic. For example, you'll find a http://blog.springsource.com/2009/01/02/spring-security-customization-part-2-adjusting-secured-session-in-real-time/[ blog article] on the SpringSource web site which describes how to use a voter to deny access in real-time to users whose accounts have been suspended. + + +[[authz-after-invocation-handling]] +==== After Invocation Handling +Whilst the `AccessDecisionManager` is called by the `AbstractSecurityInterceptor` before proceeding with the secure object invocation, some applications need a way of modifying the object actually returned by the secure object invocation. Whilst you could easily implement your own AOP concern to achieve this, Spring Security provides a convenient hook that has several concrete implementations that integrate with its ACL capabilities. + +<> illustrates Spring Security's `AfterInvocationManager` and its concrete implementations. + +[[authz-after-invocation]] +.After Invocation Implementation +image::images/after-invocation.png[] + +Like many other parts of Spring Security, `AfterInvocationManager` has a single concrete implementation, `AfterInvocationProviderManager`, which polls a list of `AfterInvocationProvider` s. Each `AfterInvocationProvider` is allowed to modify the return object or throw an `AccessDeniedException`. Indeed multiple providers can modify the object, as the result of the previous provider is passed to the next in the list. + +Please be aware that if you're using `AfterInvocationManager`, you will still need configuration attributes that allow the `MethodSecurityInterceptor`'s `AccessDecisionManager` to allow an operation. If you're using the typical Spring Security included `AccessDecisionManager` implementations, having no configuration attributes defined for a particular secure method invocation will cause each `AccessDecisionVoter` to abstain from voting. In turn, if the `AccessDecisionManager` property "`allowIfAllAbstainDecisions`" is `false`, an `AccessDeniedException` will be thrown. You may avoid this potential issue by either (i) setting "`allowIfAllAbstainDecisions`" to `true` (although this is generally not recommended) or (ii) simply ensure that there is at least one configuration attribute that an `AccessDecisionVoter` will vote to grant access for. This latter (recommended) approach is usually achieved through a `ROLE_USER` or `ROLE_AUTHENTICATED` configuration attribute. + + +[[authz-hierarchical-roles]] +==== Hierarchical Roles +It is a common requirement that a particular role in an application should automatically "include" other roles. For example, in an application which has the concept of an "admin" and a "user" role, you may want an admin to be able to do everything a normal user can. To achieve this, you can either make sure that all admin users are also assigned the "user" role. Alternatively, you can modify every access constraint which requires the "user" role to also include the "admin" role. This can get quite complicated if you have a lot of different roles in your application. + +The use of a role-hierarchy allows you to configure which roles (or authorities) should include others. An extended version of Spring Security's <>, `RoleHierarchyVoter`, is configured with a `RoleHierarchy`, from which it obtains all the "reachable authorities" which the user is assigned. A typical configuration might look like this: + +[source,xml] +---- + + + + + + + + ROLE_ADMIN > ROLE_STAFF + ROLE_STAFF > ROLE_USER + ROLE_USER > ROLE_GUEST + + + +---- + +Here we have four roles in a hierarchy `ROLE_ADMIN => ROLE_STAFF => ROLE_USER => ROLE_GUEST`. A user who is authenticated with `ROLE_ADMIN`, will behave as if they have all four roles when security contraints are evaluated against an `AccessDecisionManager` cconfigured with the above `RoleHierarchyVoter`. The `>` symbol can be thought of as meaning "includes". + +Role hierarchies offer a convenient means of simplifying the access-control configuration data for your application and/or reducing the number of authorities which you need to assign to a user. For more complex requirements you may wish to define a logical mapping between the specific access-rights your application requires and the roles that are assigned to users, translating between the two when loading the user information. + +[[secure-object-impls]] +=== Secure Object Implementations + +[[aop-alliance]] +==== AOP Alliance (MethodInvocation) Security Interceptor +Prior to Spring Security 2.0, securing `MethodInvocation` s needed quite a lot of boiler plate configuration. Now the recommended approach for method security is to use <>. This way the method security infrastructure beans are configured automatically for you so you don't really need to know about the implementation classes. We'll just provide a quick overview of the classes that are involved here. + +Method security in enforced using a `MethodSecurityInterceptor`, which secures `MethodInvocation` s. Depending on the configuration approach, an interceptor may be specific to a single bean or shared between multiple beans. The interceptor uses a `MethodSecurityMetadataSource` instance to obtain the configuration attributes that apply to a particular method invocation. `MapBasedMethodSecurityMetadataSource` is used to store configuration attributes keyed by method names (which can be wildcarded) and will be used internally when the attributes are defined in the application context using the `` or `` elements. Other implementations will be used to handle annotation-based configuration. + +===== Explicit MethodSecurityInterceptor Configuration +You can of course configure a `MethodSecurityIterceptor` directly in your application context for use with one of Spring AOP's proxying mechanisms: + +[source,xml] +---- + + + + + + + + + + + + +---- + +[[aspectj]] +==== AspectJ (JoinPoint) Security Interceptor +The AspectJ security interceptor is very similar to the AOP Alliance security interceptor discussed in the previous section. Indeed we will only discuss the differences in this section. + +The AspectJ interceptor is named `AspectJSecurityInterceptor`. Unlike the AOP Alliance security interceptor, which relies on the Spring application context to weave in the security interceptor via proxying, the `AspectJSecurityInterceptor` is weaved in via the AspectJ compiler. It would not be uncommon to use both types of security interceptors in the same application, with `AspectJSecurityInterceptor` being used for domain object instance security and the AOP Alliance `MethodSecurityInterceptor` being used for services layer security. + +Let's first consider how the `AspectJSecurityInterceptor` is configured in the Spring application context: + + +[source,xml] +---- + + + + + + + + + + + + +---- + + +As you can see, aside from the class name, the `AspectJSecurityInterceptor` is exactly the same as the AOP Alliance security interceptor. Indeed the two interceptors can share the same`securityMetadataSource`, as the `SecurityMetadataSource` works with `java.lang.reflect.Method` s rather than an AOP library-specific class. Of course, your access decisions have access to the relevant AOP library-specific invocation (ie `MethodInvocation` or `JoinPoint`) and as such can consider a range of addition criteria when making access decisions (such as method arguments). + +Next you'll need to define an AspectJ `aspect`. For example: + + +[source,java] +---- + +package org.springframework.security.samples.aspectj; + +import org.springframework.security.access.intercept.aspectj.AspectJSecurityInterceptor; +import org.springframework.security.access.intercept.aspectj.AspectJCallback; +import org.springframework.beans.factory.InitializingBean; + +public aspect DomainObjectInstanceSecurityAspect implements InitializingBean { + + private AspectJSecurityInterceptor securityInterceptor; + + pointcut domainObjectInstanceExecution(): target(PersistableEntity) + && execution(public * *(..)) && !within(DomainObjectInstanceSecurityAspect); + + Object around(): domainObjectInstanceExecution() { + if (this.securityInterceptor == null) { + return proceed(); + } + + AspectJCallback callback = new AspectJCallback() { + public Object proceedWithObject() { + return proceed(); + } + }; + + return this.securityInterceptor.invoke(thisJoinPoint, callback); + } + + public AspectJSecurityInterceptor getSecurityInterceptor() { + return securityInterceptor; + } + + public void setSecurityInterceptor(AspectJSecurityInterceptor securityInterceptor) { + this.securityInterceptor = securityInterceptor; + } + + public void afterPropertiesSet() throws Exception { + if (this.securityInterceptor == null) + throw new IllegalArgumentException("securityInterceptor required"); + } + } +} +---- + + +In the above example, the security interceptor will be applied to every instance of `PersistableEntity`, which is an abstract class not shown (you can use any other class or `pointcut` expression you like). For those curious, `AspectJCallback` is needed because the `proceed();` statement has special meaning only within an `around()` body. The `AspectJSecurityInterceptor` calls this anonymous `AspectJCallback` class when it wants the target object to continue. + +You will need to configure Spring to load the aspect and wire it with the `AspectJSecurityInterceptor`. A bean declaration which achieves this is shown below: + + +[source,xml] +---- + + + + +---- + + +That's it! Now you can create your beans from anywhere within your application, using whatever means you think fit (eg `new Person();`) and they will have the security interceptor applied. + + +[[el-access]] +=== Expression-Based Access Control +Spring Security 3.0 introduced the ability to use Spring EL expressions as an authorization mechanism in addition to the simple use of configuration attributes and access-decision voters which have seen before. Expression-based access control is built on the same architecture but allows complicated boolean logic to be encapsulated in a single expression. + + +==== Overview +Spring Security uses Spring EL for expression support and you should look at how that works if you are interested in understanding the topic in more depth. Expressions are evaluated with a "root object" as part of the evaluation context. Spring Security uses specific classes for web and method security as the root object, in order to provide built-in expressions and access to values such as the current principal. + + +[[el-common-built-in]] +===== Common Built-In ExpressionsCommon built-in expressions +The base class for expression root objects is `SecurityExpressionRoot`. This provides some common expressions which are available in both web and method security. + +[[common-expressions]] +.Common built-in expressions +|=== +| Expression | Description + +| `hasRole([role])` +| Returns `true` if the current principal has the specified role. + +| `hasAnyRole([role1,role2])` +| Returns `true` if the current principal has any of the supplied roles (given as a comma-separated list of strings) + +| `principal` +| Allows direct access to the principal object representing the current user + +| `authentication` +| Allows direct access to the current `Authentication` object obtained from the `SecurityContext` + +| `permitAll` +| Always evaluates to `true` + +| `denyAll` +| Always evaluates to `false` + +| `isAnonymous()` +| Returns `true` if the current principal is an anonymous user + +| `isRememberMe()` +| Returns `true` if the current principal is a remember-me user + +| `isAuthenticated()` +| Returns `true` if the user is not anonymous + +| `isFullyAuthenticated()` +| Returns `true` if the user is not an anonymous or a remember-me user +|=== + + + +[[el-access-web]] +==== Web Security Expressions +To use expressions to secure individual URLs, you would first need to set the `use-expressions` attribute in the `` element to `true`. Spring Security will then expect the `access` attributes of the `` elements to contain Spring EL expressions. The expressions should evaluate to a boolean, defining whether access should be allowed or not. For example: + +[source,xml] +---- + + + + ... + + +---- + +Here we have defined that the "admin" area of an application (defined by the URL pattern) should only be available to users who have the granted authority "admin" and whose IP address matches a local subnet. We've already seen the built-in `hasRole` expression in the previous section. The expression `hasIpAddress` is an additional built-in expression which is specific to web security. It is defined by the `WebSecurityExpressionRoot` class, an instance of which is used as the expression root object when evaluation web-access expressions. This object also directly exposed the `HttpServletRequest` object under the name `request` so you can invoke the request directly in an expressio +If expressions are being used, a `WebExpressionVoter` will be added to the `AccessDecisionManager` which is used by the namespace. So if you aren't using the namespace and want to use expressions, you will have to add one of these to your configuration. + + +==== Method Security Expressions +Method security is a bit more complicated than a simple allow or deny rule. Spring Security 3.0 introduced some new annotations in order to allow comprehensive support for the use of expressions. + + +[[el-pre-post-annotations]] +===== @Pre and @Post Annotations +There are four annotations which support expression attributes to allow pre and post-invocation authorization checks and also to support filtering of submitted collection arguments or return values. They are `@PreAuthorize`, `@PreFilter`, `@PostAuthorize` and `@PostFilter`. Their use is enabled through the `global-method-security` namespace element: + +[source,xml] +---- + +---- + +====== Access Control using @PreAuthorize and @PostAuthorize +The most obviously useful annotation is `@PreAuthorize` which decides whether a method can actually be invoked or not. For example (from the"Contacts" sample application) + +[source,java] +---- +@PreAuthorize("hasRole('ROLE_USER')") +public void create(Contact contact); +---- + +which means that access will only be allowed for users with the role "ROLE_USER". + + +[[el-pre-post-annotations-arguments]] +* **Resolving method arguments** +Obviously the same thing could easily be achieved using a traditional configuration and a simple configuration attribute for the required role. But what about: + +[source,java] +---- +@PreAuthorize("hasPermission(#contact, 'admin')") +public void deletePermission(Contact contact, Sid recipient, Permission permission); +---- + +Here we're actually using a method argument as part of the expression to decide whether the current user has the "admin"permission for the given contact. The built-in `hasPermission()` expression is linked into the Spring Security ACL module through the application context, as we'll<>. You can access any of the method arguments by name as expression variables. + +There are a number of ways in which Spring Security can resolve the method arguments. Spring Security uses `DefaultSecurityParameterNameDiscoverer` to discover the parameter names. By default, the following options are tried for a method as a whole. + +* If Spring Security's `@P` annotation is present on a single argument to the method, the value will be used. This is useful for interfaces compiled with a JDK prior to JDK 8 which do not contain any information about the parameter names. For example: + ++ + +[source,java] +---- +import org.springframework.security.access.method.P; + +... + +@PreAuthorize("#c.name == authentication.name") +public void doSomething(@P("c") Contact contact); +---- + ++ + +Behind the scenes this use implemented using `AnnotationParameterNameDiscoverer` which can be customized to support the value attribute of any specified annotation. + +* If Spring Data's `@Param` annotation is present on at least one parameter for the method, the value will be used. This is useful for interfaces compiled with a JDK prior to JDK 8 which do not contain any information about the parameter names. For example: + ++ + +[source,java] +---- +import org.springframework.data.repository.query.Param; + +... + +@PreAuthorize("#n == authentication.name") +Contact findContactByName(@Param("n") String name); +---- + ++ + +Behind the scenes this use implemented using `AnnotationParameterNameDiscoverer` which can be customized to support the value attribute of any specified annotation. + +* If JDK 8 was used to compile the source with the -parameters argument and Spring 4+ is being used, then the standard JDK reflection API is used to discover the parameter names. This works on both classes and interfaces. + +* Last, if the code was compiled with the debug symbols, the parameter names will be discovered using the debug symbols. This will not work for interfaces since they do not have debug information about the parameter names. For interfaces, annotations or the JDK 8 approach must be used. + +[[el-pre-post-annotations-spel]] +* **Method Expressions and SpEL** +Any Spring-EL functionality is available within the expression, so you can also access properties on the arguments. For example, if you wanted a particular method to only allow access to a user whose username matched that of the contact, you could write + + +[source,java] +---- +@PreAuthorize("#contact.name == authentication.name") +public void doSomething(Contact contact); +---- + +Here we are accessing another built–in expression, `authentication`, which is the `Authentication` stored in the security context. You can also access its "principal" property directly, using the expression `principal`. The value will often be a `UserDetails` instance, so you might use an expression like `principal.username` or `principal.enabled`. + +[[el-pre-post-annotations-post]] +* **Accessing the return value** +Less commonly, you may wish to perform an access-control check after the method has been invoked. This can be achieved using the `@PostAuthorize` annotation. To access the return value from a method, use the built–in name `returnObject` in the expression. + + +====== Filtering using +`@PreFilter` and `@PostFilter` +As you may already be aware, Spring Security supports filtering of collections and arrays and this can now be achieved using expressions. This is most commonly performed on the return value of a method. For example: + +[source,java] +---- +@PreAuthorize("hasRole('ROLE_USER')") +@PostFilter("hasPermission(filterObject, 'read') or hasPermission(filterObject, 'admin')") +public List getAll(); +---- + +When using the `@PostFilter` annotation, Spring Security iterates through the returned collection and removes any elements for which the supplied expression is false. The name `filterObject` refers to the current object in the collection. You can also filter before the method call, using `@PreFilter`, though this is a less common requirement. The syntax is just the same, but if there is more than one argument which is a collection type then you have to select one by name using the `filterTarget` property of this annotation. + +Note that filtering is obviously not a substitute for tuning your data retrieval queries. If you are filtering large collections and removing many of the entries then this is likely to be inefficient. + + +[[el-method-built-in]] +===== Built-In Expressions +There are some built-in expressions which are specific to method security, which we have already seen in use above. The `filterTarget` and `returnValue` values are simple enough, but the use of the `hasPermission()` expression warrants a closer look. + + +[[el-permission-evaluator]] +====== The PermissionEvaluator interface +`hasPermission()` expressions are delegated to an instance of `PermissionEvaluator`. It is intended to bridge between the expression system and Spring Security's ACL system, allowing you to specify authorization constraints on domain objects, based on abstract permissions. It has no explicit dependencies on the ACL module, so you could swap that out for an alternative implementation if required. The interface has two methods: + +[source,java] +---- +boolean hasPermission(Authentication authentication, Object targetDomainObject, + Object permission); + +boolean hasPermission(Authentication authentication, Serializable targetId, + String targetType, Object permission); +---- + +which map directly to the available versions of the expression, with the exception that the first argument (the `Authentication` object) is not supplied. The first is used in situations where the domain object, to which access is being controlled, is already loaded. Then expression will return true if the current user has the given permission for that object. The second version is used in cases where the object is not loaded, but its identifier is known. An abstract "type" specifier for the domain object is also required, allowing the correct ACL permissions to be loaded. This has traditionally been the Java class of the object, but does not have to be as long as it is consistent with how the permissions are loaded. + +To use `hasPermission()` expressions, you have to explicitly configure a `PermissionEvaluator` in your application context. This would look something like this: + +[source,xml] +---- + + + + + + + +---- + +Where `myPermissionEvaluator` is the bean which implements `PermissionEvaluator`. Usually this will be the implementation from the ACL module which is called`AclPermissionEvaluator`. See the "Contacts" sample application configuration for more details. + +[[advanced-topics]] +== Additional Topics +In this part we cover features which require a knowledge of previous chapters as well as some of the more advanced and less-commonly used features of the framework. + +[[domain-acls]] +=== Domain Object Security (ACLs) + +[[domain-acls-overview]] +==== Overview +Complex applications often will find the need to define access permissions not simply at a web request or method invocation level. Instead, security decisions need to comprise both who (`Authentication`), where (`MethodInvocation`) and what (`SomeDomainObject`). In other words, authorization decisions also need to consider the actual domain object instance subject of a method invocation. + +Imagine you're designing an application for a pet clinic. There will be two main groups of users of your Spring-based application: staff of the pet clinic, as well as the pet clinic's customers. The staff will have access to all of the data, whilst your customers will only be able to see their own customer records. To make it a little more interesting, your customers can allow other users to see their customer records, such as their "puppy preschool" mentor or president of their local "Pony Club". Using Spring Security as the foundation, you have several approaches that can be used: + +* Write your business methods to enforce the security. You could consult a collection within the `Customer` domain object instance to determine which users have access. By using the `SecurityContextHolder.getContext().getAuthentication()`, you'll be able to access the `Authentication` object. +* Write an `AccessDecisionVoter` to enforce the security from the `GrantedAuthority[]` s stored in the `Authentication` object. This would mean your `AuthenticationManager` would need to populate the `Authentication` with custom `GrantedAuthority`[]s representing each of the `Customer` domain object instances the principal has access to. +* Write an `AccessDecisionVoter` to enforce the security and open the target `Customer` domain object directly. This would mean your voter needs access to a DAO that allows it to retrieve the `Customer` object. It would then access the `Customer` object's collection of approved users and make the appropriate decision. + + +Each one of these approaches is perfectly legitimate. However, the first couples your authorization checking to your business code. The main problems with this include the enhanced difficulty of unit testing and the fact it would be more difficult to reuse the `Customer` authorization logic elsewhere. Obtaining the `GrantedAuthority[]` s from the `Authentication` object is also fine, but will not scale to large numbers of `Customer` s. If a user might be able to access 5,000 `Customer` s (unlikely in this case, but imagine if it were a popular vet for a large Pony Club!) the amount of memory consumed and time required to construct the `Authentication` object would be undesirable. The final method, opening the `Customer` directly from external code, is probably the best of the three. It achieves separation of concerns, and doesn't misuse memory or CPU cycles, but it is still inefficient in that both the `AccessDecisionVoter` and the eventual business method itself will perform a call to the DAO responsible for retrieving the `Customer` object. Two accesses per method invocation is clearly undesirable. In addition, with every approach listed you'll need to write your own access control list (ACL) persistence and business logic from scratch. + +Fortunately, there is another alternative, which we'll talk about below. + + +[[domain-acls-key-concepts]] +==== Key Concepts +Spring Security's ACL services are shipped in the `spring-security-acl-xxx.jar`. You will need to add this JAR to your classpath to use Spring Security's domain object instance security capabilities. + +Spring Security's domain object instance security capabilities centre on the concept of an access control list (ACL). Every domain object instance in your system has its own ACL, and the ACL records details of who can and can't work with that domain object. With this in mind, Spring Security delivers three main ACL-related capabilities to your application: + +* A way of efficiently retrieving ACL entries for all of your domain objects (and modifying those ACLs) +* A way of ensuring a given principal is permitted to work with your objects, before methods are called +* A way of ensuring a given principal is permitted to work with your objects (or something they return), after methods are called + +As indicated by the first bullet point, one of the main capabilities of the Spring Security ACL module is providing a high-performance way of retrieving ACLs. This ACL repository capability is extremely important, because every domain object instance in your system might have several access control entries, and each ACL might inherit from other ACLs in a tree-like structure (this is supported out-of-the-box by Spring Security, and is very commonly used). Spring Security's ACL capability has been carefully designed to provide high performance retrieval of ACLs, together with pluggable caching, deadlock-minimizing database updates, independence from ORM frameworks (we use JDBC directly), proper encapsulation, and transparent database updating. + +Given databases are central to the operation of the ACL module, let's explore the four main tables used by default in the implementation. The tables are presented below in order of size in a typical Spring Security ACL deployment, with the table with the most rows listed last: + + + +* ACL_SID allows us to uniquely identify any principal or authority in the system ("SID" stands for "security identity"). The only columns are the ID, a textual representation of the SID, and a flag to indicate whether the textual representation refers to a principal name or a `GrantedAuthority`. Thus, there is a single row for each unique principal or `GrantedAuthority`. When used in the context of receiving a permission, a SID is generally called a "recipient". + +* ACL_CLASS allows us to uniquely identify any domain object class in the system. The only columns are the ID and the Java class name. Thus, there is a single row for each unique Class we wish to store ACL permissions for. + +* ACL_OBJECT_IDENTITY stores information for each unique domain object instance in the system. Columns include the ID, a foreign key to the ACL_CLASS table, a unique identifier so we know which ACL_CLASS instance we're providing information for, the parent, a foreign key to the ACL_SID table to represent the owner of the domain object instance, and whether we allow ACL entries to inherit from any parent ACL. We have a single row for every domain object instance we're storing ACL permissions for. + +* Finally, ACL_ENTRY stores the individual permissions assigned to each recipient. Columns include a foreign key to the ACL_OBJECT_IDENTITY, the recipient (ie a foreign key to ACL_SID), whether we'll be auditing or not, and the integer bit mask that represents the actual permission being granted or denied. We have a single row for every recipient that receives a permission to work with a domain object. + + + + +As mentioned in the last paragraph, the ACL system uses integer bit masking. Don't worry, you need not be aware of the finer points of bit shifting to use the ACL system, but suffice to say that we have 32 bits we can switch on or off. Each of these bits represents a permission, and by default the permissions are read (bit 0), write (bit 1), create (bit 2), delete (bit 3) and administer (bit 4). It's easy to implement your own `Permission` instance if you wish to use other permissions, and the remainder of the ACL framework will operate without knowledge of your extensions. + +It is important to understand that the number of domain objects in your system has absolutely no bearing on the fact we've chosen to use integer bit masking. Whilst you have 32 bits available for permissions, you could have billions of domain object instances (which will mean billions of rows in ACL_OBJECT_IDENTITY and quite probably ACL_ENTRY). We make this point because we've found sometimes people mistakenly believe they need a bit for each potential domain object, which is not the case. + +Now that we've provided a basic overview of what the ACL system does, and what it looks like at a table structure, let's explore the key interfaces. The key interfaces are: + + +* `Acl`: Every domain object has one and only one `Acl` object, which internally holds the `AccessControlEntry` s as well as knows the owner of the `Acl`. An Acl does not refer directly to the domain object, but instead to an `ObjectIdentity`. The `Acl` is stored in the ACL_OBJECT_IDENTITY table. + +* `AccessControlEntry`: An `Acl` holds multiple `AccessControlEntry` s, which are often abbreviated as ACEs in the framework. Each ACE refers to a specific tuple of`Permission`, `Sid` and `Acl`. An ACE can also be granting or non-granting and contain audit settings. The ACE is stored in the ACL_ENTRY table. + +* `Permission`: A permission represents a particular immutable bit mask, and offers convenience functions for bit masking and outputting information. The basic permissions presented above (bits 0 through 4) are contained in the `BasePermission` class. + +* `Sid`: The ACL module needs to refer to principals and `GrantedAuthority[]` s. A level of indirection is provided by the `Sid` interface, which is an abbreviation of "security identity". Common classes include `PrincipalSid` (to represent the principal inside an `Authentication` object) and `GrantedAuthoritySid`. The security identity information is stored in the ACL_SID table. + +* `ObjectIdentity`: Each domain object is represented internally within the ACL module by an `ObjectIdentity`. The default implementation is called `ObjectIdentityImpl`. + +* `AclService`: Retrieves the `Acl` applicable for a given `ObjectIdentity`. In the included implementation (`JdbcAclService`), retrieval operations are delegated to a `LookupStrategy`. The `LookupStrategy` provides a highly optimized strategy for retrieving ACL information, using batched retrievals `(BasicLookupStrategy`) and supporting custom implementations that leverage materialized views, hierarchical queries and similar performance-centric, non-ANSI SQL capabilities. + +* `MutableAclService`: Allows a modified `Acl` to be presented for persistence. It is not essential to use this interface if you do not wish. + + + +Please note that our out-of-the-box AclService and related database classes all use ANSI SQL. This should therefore work with all major databases. At the time of writing, the system had been successfully tested using Hypersonic SQL, PostgreSQL, Microsoft SQL Server and Oracle. + +Two samples ship with Spring Security that demonstrate the ACL module. The first is the Contacts Sample, and the other is the Document Management System (DMS) Sample. We suggest taking a look over these for examples. + + +[[domain-acls-getting-started]] +==== Getting Started +To get starting using Spring Security's ACL capability, you will need to store your ACL information somewhere. This necessitates the instantiation of a `DataSource` using Spring. The `DataSource` is then injected into a `JdbcMutableAclService` and `BasicLookupStrategy` instance. The latter provides high-performance ACL retrieval capabilities, and the former provides mutator capabilities. Refer to one of the samples that ship with Spring Security for an example configuration. You'll also need to populate the database with the four ACL-specific tables listed in the last section (refer to the ACL samples for the appropriate SQL statements). + +Once you've created the required schema and instantiated `JdbcMutableAclService`, you'll next need to ensure your domain model supports interoperability with the Spring Security ACL package. Hopefully `ObjectIdentityImpl` will prove sufficient, as it provides a large number of ways in which it can be used. Most people will have domain objects that contain a `public Serializable getId()` method. If the return type is long, or compatible with long (eg an int), you will find you need not give further consideration to `ObjectIdentity` issues. Many parts of the ACL module rely on long identifiers. If you're not using long (or an int, byte etc), there is a very good chance you'll need to reimplement a number of classes. We do not intend to support non-long identifiers in Spring Security's ACL module, as longs are already compatible with all database sequences, the most common identifier data type, and are of sufficient length to accommodate all common usage scenarios. + +The following fragment of code shows how to create an `Acl`, or modify an existing`Acl`: + +[source,java] +---- +// Prepare the information we'd like in our access control entry (ACE) +ObjectIdentity oi = new ObjectIdentityImpl(Foo.class, new Long(44)); +Sid sid = new PrincipalSid("Samantha"); +Permission p = BasePermission.ADMINISTRATION; + +// Create or update the relevant ACL +MutableAcl acl = null; +try { + acl = (MutableAcl) aclService.readAclById(oi); +} catch (NotFoundException nfe) { + acl = aclService.createAcl(oi); +} + +// Now grant some permissions via an access control entry (ACE) +acl.insertAce(acl.getEntries().length, p, sid, true); +aclService.updateAcl(acl); +---- + + + +In the example above, we're retrieving the ACL associated with the "Foo" domain object with identifier number 44. We're then adding an ACE so that a principal named "Samantha" can "administer" the object. The code fragment is relatively self-explanatory, except the insertAce method. The first argument to the insertAce method is determining at what position in the Acl the new entry will be inserted. In the example above, we're just putting the new ACE at the end of the existing ACEs. The final argument is a boolean indicating whether the ACE is granting or denying. Most of the time it will be granting (true), but if it is denying (false), the permissions are effectively being blocked. + +Spring Security does not provide any special integration to automatically create, update or delete ACLs as part of your DAO or repository operations. Instead, you will need to write code like shown above for your individual domain objects. It's worth considering using AOP on your services layer to automatically integrate the ACL information with your services layer operations. We've found this quite an effective approach in the past. + +Once you've used the above techniques to store some ACL information in the database, the next step is to actually use the ACL information as part of authorization decision logic. You have a number of choices here. You could write your own `AccessDecisionVoter` or `AfterInvocationProvider` that respectively fires before or after a method invocation. Such classes would use `AclService` to retrieve the relevant ACL and then call `Acl.isGranted(Permission[] permission, Sid[] sids, boolean administrativeMode)` to decide whether permission is granted or denied. Alternately, you could use our `AclEntryVoter`, `AclEntryAfterInvocationProvider` or `AclEntryAfterInvocationCollectionFilteringProvider` classes. All of these classes provide a declarative-based approach to evaluating ACL information at runtime, freeing you from needing to write any code. Please refer to the sample applications to learn how to use these classes. + + +[[preauth]] +=== Pre-Authentication Scenarios +There are situations where you want to use Spring Security for authorization, but the user has already been reliably authenticated by some external system prior to accessing the application. We refer to these situations as "pre-authenticated" scenarios. Examples include X.509, Siteminder and authentication by the J2EE container in which the application is running. When using pre-authentication, Spring Security has to + +* Identify the user making the request. + +* Obtain the authorities for the user. + + +The details will depend on the external authentication mechanism. A user might be identified by their certificate information in the case of X.509, or by an HTTP request header in the case of Siteminder. If relying on container authentication, the user will be identified by calling the `getUserPrincipal()` method on the incoming HTTP request. In some cases, the external mechanism may supply role/authority information for the user but in others the authorities must be obtained from a separate source, such as a `UserDetailsService`. + + +==== Pre-Authentication Framework Classes +Because most pre-authentication mechanisms follow the same pattern, Spring Security has a set of classes which provide an internal framework for implementing pre-authenticated authentication providers. This removes duplication and allows new implementations to be added in a structured fashion, without having to write everything from scratch. You don't need to know about these classes if you want to use something like <>, as it already has a namespace configuration option which is simpler to use and get started with. If you need to use explicit bean configuration or are planning on writing your own implementation then an understanding of how the provided implementations work will be useful. You will find classes under the `org.springframework.security.web.authentication.preauth`. We just provide an outline here so you should consult the Javadoc and source where appropriate. + + +===== AbstractPreAuthenticatedProcessingFilter +This class will check the current contents of the security context and, if empty, it will attempt to extract user information from the HTTP request and submit it to the `AuthenticationManager`. Subclasses override the following methods to obtain this information: + +[source,java] +---- +protected abstract Object getPreAuthenticatedPrincipal(HttpServletRequest request); + +protected abstract Object getPreAuthenticatedCredentials(HttpServletRequest request); +---- + + +After calling these, the filter will create a `PreAuthenticatedAuthenticationToken` containing the returned data and submit it for authentication. By "authentication" here, we really just mean further processing to perhaps load the user's authorities, but the standard Spring Security authentication architecture is followed. + +Like other Spring Security authentication filters, the pre-authentication filter has an `authenticationDetailsSource` property which by default will create a `WebAuthenticationDetails` object to store additional information such as the session-identifier and originating IP address in the `details` property of the `Authentication` object. In cases where user role information can be obtained from the pre-authentication mechanism, the data is also stored in this property, with the details implementing the `GrantedAuthoritiesContainer` interface. This enables the authentication provider to read the authorities which were externally allocated to the user. We'll look at a concrete example next. + + +[[j2ee-preauth-details]] +====== J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource +If the filter is configured with an `authenticationDetailsSource` which is an instance of this class, the authority information is obtained by calling the `isUserInRole(String role)` method for each of a pre-determined set of "mappable roles". The class gets these from a configured `MappableAttributesRetriever`. Possible implementations include hard-coding a list in the application context and reading the role information from the `` information in a `web.xml` file. The pre-authentication sample application uses the latter approach. + +There is an additional stage where the roles (or attributes) are mapped to Spring Security `GrantedAuthority` objects using a configured `Attributes2GrantedAuthoritiesMapper`. The default will just add the usual `ROLE_` prefix to the names, but it gives you full control over the behaviour. + + +===== PreAuthenticatedAuthenticationProvider +The pre-authenticated provider has little more to do than load the `UserDetails` object for the user. It does this by delegating to a `AuthenticationUserDetailsService`. The latter is similar to the standard `UserDetailsService` but takes an `Authentication` object rather than just user name: + +[source,java] +---- +public interface AuthenticationUserDetailsService { + UserDetails loadUserDetails(Authentication token) throws UsernameNotFoundException; +} +---- + +This interface may have also other uses but with pre-authentication it allows access to the authorities which were packaged in the `Authentication` object, as we saw in the previous section. the `PreAuthenticatedGrantedAuthoritiesUserDetailsService` class does this. Alternatively, it may delegate to a standard `UserDetailsService` via the `UserDetailsByNameServiceWrapper` implementation. + +===== Http403ForbiddenEntryPoint +The `AuthenticationEntryPoint` was discussed in the <> chapter. Normally it is responsible for kick-starting the authentication process for an unauthenticated user (when they try to access a protected resource), but in the pre-authenticated case this doesn't apply. You would only configure the `ExceptionTranslationFilter` with an instance of this class if you aren't using pre-authentication in combination with other authentication mechanisms. It will be called if the user is rejected by the `AbstractPreAuthenticatedProcessingFilter` resulting in a null authentication. It always returns a `403`-forbidden response code if called. + + +==== Concrete Implementations +X.509 authentication is covered in its <>. Here we'll look at some classes which provide support for other pre-authenticated scenarios. + + +===== Request-Header Authentication (Siteminder) +An external authentication system may supply information to the application by setting specific headers on the HTTP request. A well known example of this is Siteminder, which passes the username in a header called `SM_USER`. This mechanism is supported by the class `RequestHeaderAuthenticationFilter` which simply extracts the username from the header. It defaults to using the name `SM_USER` as the header name. See the Javadoc for more details. + +[TIP] +==== +Note that when using a system like this, the framework performs no authentication checks at all and it is __extremely__ important that the external system is configured properly and protects all access to the application. If an attacker is able to forge the headers in their original request without this being detected then they could potentially choose any username they wished. +==== + +====== Siteminder Example Configuration +A typical configuration using this filter would look like this: + +[source,xml] +---- + + + + + + + + + + + + + + + + + + + + + +---- + +We've assumed here that the <> is being used for configuration. It's also assumed that you have added a `UserDetailsService` (called "userDetailsService") to your configuration to load the user's roles. + + +===== J2EE Container Authentication +The class `J2eePreAuthenticatedProcessingFilter` will extract the username from the `userPrincipal` property of the `HttpServletRequest`. Use of this filter would usually be combined with the use of J2EE roles as described above in <>. + +There is a sample application in the codebase which uses this approach, so get hold of the code from subversion and have a look at the application context file if you are interested. The code is in the `samples/preauth` directory. + + +[[ldap]] +=== LDAP Authentication + + +[[ldap-overview]] +==== Overview +LDAP is often used by organizations as a central repository for user information and as an authentication service. It can also be used to store the role information for application users. + +There are many different scenarios for how an LDAP server may be configured so Spring Security's LDAP provider is fully configurable. It uses separate strategy interfaces for authentication and role retrieval and provides default implementations which can be configured to handle a wide range of situations. + +You should be familiar with LDAP before trying to use it with Spring Security. The following link provides a good introduction to the concepts involved and a guide to setting up a directory using the free LDAP server OpenLDAP: http://www.zytrax.com/books/ldap/[http://www.zytrax.com/books/ldap/]. Some familiarity with the JNDI APIs used to access LDAP from Java may also be useful. We don't use any third-party LDAP libraries (Mozilla, JLDAP etc.) in the LDAP provider, but extensive use is made of Spring LDAP, so some familiarity with that project may be useful if you plan on adding your own customizations. + +When using LDAP authentication, it is important to ensure that you configure LDAP connection pooling properly. If you are unfamiliar with how to do this, you can refer to the http://docs.oracle.com/javase/jndi/tutorial/ldap/connect/config.html[Java LDAP documentation]. + +==== Using LDAP with Spring Security +LDAP authentication in Spring Security can be roughly divided into the following stages. + +* Obtaining the unique LDAP "Distinguished Name", or DN, from the login name. This will often mean performing a search in the directory, unless the exact mapping of usernames to DNs is known in advance. So a user might enter the name "joe" when logging in, but the actual name used to authenticate to LDAP will be the full DN, such as`uid=joe,ou=users,dc=springsource,dc=com`. + +* Authenticating the user, either by "binding" as that user or by performing a remote "compare" operation of the user's password against the password attribute in the directory entry for the DN. + +* Loading the list of authorities for the user. + +The exception is when the LDAP directory is just being used to retrieve user information and authenticate against it locally. This may not be possible as directories are often set up with limited read access for attributes such as user passwords. + +We will look at some configuration scenarios below. For full information on available configuration options, please consult the security namespace schema (information from which should be available in your XML editor). + + +[[ldap-server]] +==== Configuring an LDAP Server +The first thing you need to do is configure the server against which authentication should take place. This is done using the `` element from the security namespace. This can be configured to point at an external LDAP server, using the `url` attribute: + +[source,xml] +---- + +---- + +===== Using an Embedded Test Server +The `` element can also be used to create an embedded server, which can be very useful for testing and demonstrations. In this case you use it without the `url` attribute: + +[source,xml] +---- + +---- + +Here we've specified that the root DIT of the directory should be "dc=springframework,dc=org", which is the default. Used this way, the namespace parser will create an embedded Apache Directory server and scan the classpath for any LDIF files, which it will attempt to load into the server. You can customize this behaviour using the `ldif` attribute, which defines an LDIF resource to be loaded: + +[source,xml] +---- + +---- + +This makes it a lot easier to get up and running with LDAP, since it can be inconvenient to work all the time with an external server. It also insulates the user from the complex bean configuration needed to wire up an Apache Directory server. Using plain Spring Beans the configuration would be much more cluttered. You must have the necessary Apache Directory dependency jars available for your application to use. These can be obtained from the LDAP sample application. + +===== Using Bind Authentication +This is the most common LDAP authentication scenario. + +[source,xml] +---- + +---- + +This simple example would obtain the DN for the user by substituting the user login name in the supplied pattern and attempting to bind as that user with the login password. This is OK if all your users are stored under a single node in the directory. If instead you wished to configure an LDAP search filter to locate the user, you could use the following: + +[source,xml] +---- + +---- + +If used with the server definition above, this would perform a search under the DN `ou=people,dc=springframework,dc=org` using the value of the `user-search-filter` attribute as a filter. Again the user login name is substituted for the parameter in the filter name, so it will search for an entry with the `uid` attribute equal to the user name. If `user-search-base` isn't supplied, the search will be performed from the root. + +===== Loading Authorities +How authorities are loaded from groups in the LDAP directory is controlled by the following attributes. + +* `group-search-base`. Defines the part of the directory tree under which group searches should be performed. +* `group-role-attribute`. The attribute which contains the name of the authority defined by the group entry. Defaults to`cn` +* `group-search-filter`. The filter which is used to search for group membership. The default is`uniqueMember={0}`, corresponding to the `groupOfUniqueNames` LDAP class footnote:[Note that this is different from the default configuration of the underlying `DefaultLdapAuthoritiesPopulator` which uses `member={0}`.]. In this case, the substituted parameter is the full distinguished name of the user. The parameter `{1}` can be used if you want to filter on the login name. + +So if we used the following configuration + +[source,xml] +---- + +---- + +and authenticated successfully as user "ben", the subsequent loading of authorities would perform a search under the directory entry`ou=groups,dc=springframework,dc=org`, looking for entries which contain the attribute `uniqueMember` with value `uid=ben,ou=people,dc=springframework,dc=org`. By default the authority names will have the prefix `ROLE_` prepended. You can change this using the `role-prefix` attribute. If you don't want any prefix, use `role-prefix="none"`. For more information on loading authorities, see the Javadoc for the `DefaultLdapAuthoritiesPopulator` class. + +==== Implementation Classes +The namespace configuration options we've used above are simple to use and much more concise than using Spring beans explicitly. There are situations when you may need to know how to configure Spring Security LDAP directly in your application context. You may wish to customize the behaviour of some of the classes, for example. If you're happy using namespace configuration then you can skip this section and the next one. + +The main LDAP provider class, `LdapAuthenticationProvider`, doesn't actually do much itself but delegates the work to two other beans, an `LdapAuthenticator` and an `LdapAuthoritiesPopulator` which are responsible for authenticating the user and retrieving the user's set of `GrantedAuthority` s respectively. + + +[[ldap-ldap-authenticators]] +===== LdapAuthenticator Implementations +The authenticator is also responsible for retrieving any required user attributes. This is because the permissions on the attributes may depend on the type of authentication being used. For example, if binding as the user, it may be necessary to read them with the user's own permissions. + +There are currently two authentication strategies supplied with Spring Security: + +* Authentication directly to the LDAP server ("bind" authentication). + +* Password comparison, where the password supplied by the user is compared with the one stored in the repository. This can either be done by retrieving the value of the password attribute and checking it locally or by performing an LDAP "compare" operation, where the supplied password is passed to the server for comparison and the real password value is never retrieved. + +[[ldap-ldap-authenticators-common]] +====== Common Functionality +Before it is possible to authenticate a user (by either strategy), the distinguished name (DN) has to be obtained from the login name supplied to the application. This can be done either by simple pattern-matching (by setting the `setUserDnPatterns` array property) or by setting the `userSearch` property. For the DN pattern-matching approach, a standard Java pattern format is used, and the login name will be substituted for the parameter `{0}`. The pattern should be relative to the DN that the configured `SpringSecurityContextSource` will bind to (see the section on <> for more information on this). For example, if you are using an LDAP server with the URL`ldap://monkeymachine.co.uk/dc=springframework,dc=org`, and have a pattern `uid={0},ou=greatapes`, then a login name of "gorilla" will map to a DN`uid=gorilla,ou=greatapes,dc=springframework,dc=org`. Each configured DN pattern will be tried in turn until a match is found. For information on using a search, see the section on <> below. A combination of the two approaches can also be used - the patterns will be checked first and if no matching DN is found, the search will be used. + + +[[ldap-ldap-authenticators-bind]] +====== BindAuthenticator +The class `BindAuthenticator` in the package `org.springframework.security.ldap.authentication` implements the bind authentication strategy. It simply attempts to bind as the user. + + +[[ldap-ldap-authenticators-password]] +====== PasswordComparisonAuthenticator +The class `PasswordComparisonAuthenticator` implements the password comparison authentication strategy. + + +[[ldap-context-source]] +===== Connecting to the LDAP Server +The beans discussed above have to be able to connect to the server. They both have to be supplied with a `SpringSecurityContextSource` which is an extension of Spring LDAP's `ContextSource`. Unless you have special requirements, you will usually configure a `DefaultSpringSecurityContextSource` bean, which can be configured with the URL of your LDAP server and optionally with the username and password of a "manager" user which will be used by default when binding to the server (instead of binding anonymously). For more information read the Javadoc for this class and for Spring LDAP's `AbstractContextSource`. + + +[[ldap-searchobjects]] +===== LDAP Search Objects +Often a more complicated strategy than simple DN-matching is required to locate a user entry in the directory. This can be encapsulated in an `LdapUserSearch` instance which can be supplied to the authenticator implementations, for example, to allow them to locate a user. The supplied implementation is `FilterBasedLdapUserSearch`. + + +[[ldap-searchobjects-filter]] +====== FilterBasedLdapUserSearch +This bean uses an LDAP filter to match the user object in the directory. The process is explained in the Javadoc for the corresponding search method on thehttp://java.sun.com/j2se/1.4.2/docs/api/javax/naming/directory/DirContext.html#search(javax.naming.Name,%20java.lang.String,%20java.lang.Object[],%20javax.naming.directory.SearchControls)[JDK DirContext class]. As explained there, the search filter can be supplied with parameters. For this class, the only valid parameter is `{0}` which will be replaced with the user's login name. + + +[[ldap-authorities]] +===== LdapAuthoritiesPopulator +After authenticating the user successfully, the `LdapAuthenticationProvider` will attempt to load a set of authorities for the user by calling the configured `LdapAuthoritiesPopulator` bean. The `DefaultLdapAuthoritiesPopulator` is an implementation which will load the authorities by searching the directory for groups of which the user is a member (typically these will be `groupOfNames` or `groupOfUniqueNames` entries in the directory). Consult the Javadoc for this class for more details on how it works. + +If you want to use LDAP only for authentication, but load the authorities from a difference source (such as a database) then you can provide your own implementation of this interface and inject that instead. + +[[ldap-bean-config]] +===== Spring Bean Configuration +A typical configuration, using some of the beans we've discussed here, might look like this: + +[source,xml] +---- + + + + + + + + + + + + uid={0},ou=people + + + + + + + + + + + +---- + +This would set up the provider to access an LDAP server with URL `ldap://monkeymachine:389/dc=springframework,dc=org`. Authentication will be performed by attempting to bind with the DN`uid=,ou=people,dc=springframework,dc=org`. After successful authentication, roles will be assigned to the user by searching under the DN `ou=groups,dc=springframework,dc=org` with the default filter `(member=)`. The role name will be taken from the "ou" attribute of each match. + +To configure a user search object, which uses the filter `(uid=)` for use instead of the DN-pattern (or in addition to it), you would configure the following bean + +[source,xml] +---- + + + + + + +---- + +and use it by setting the `BindAuthenticator` bean's `userSearch` property. The authenticator would then call the search object to obtain the correct user's DN before attempting to bind as this user. + + +[[ldap-custom-user-details]] +===== LDAP Attributes and Customized UserDetails +The net result of an authentication using `LdapAuthenticationProvider` is the same as a normal Spring Security authentication using the standard `UserDetailsService` interface. A `UserDetails` object is created and stored in the returned `Authentication` object. As with using a `UserDetailsService`, a common requirement is to be able to customize this implementation and add extra properties. When using LDAP, these will normally be attributes from the user entry. The creation of the `UserDetails` object is controlled by the provider's `UserDetailsContextMapper` strategy, which is responsible for mapping user objects to and from LDAP context data: + +[source,java] +---- +public interface UserDetailsContextMapper { + + UserDetails mapUserFromContext(DirContextOperations ctx, String username, + Collection authorities); + + void mapUserToContext(UserDetails user, DirContextAdapter ctx); +} +---- + +Only the first method is relevant for authentication. If you provide an implementation of this interface and inject it into the `LdapAuthenticationProvider`, you have control over exactly how the UserDetails object is created. The first parameter is an instance of Spring LDAP's `DirContextOperations` which gives you access to the LDAP attributes which were loaded during authentication. the `username` parameter is the name used to authenticate and the final parameter is the collection of authorities loaded for the user by the configured`LdapAuthoritiesPopulator`. + +The way the context data is loaded varies slightly depending on the type of authentication you are using. With the `BindAuthenticator`, the context returned from the bind operation will be used to read the attributes, otherwise the data will be read using the standard context obtained from the configured `ContextSource` (when a search is configured to locate the user, this will be the data returned by the search object). + + +[[ldap-active-directory]] +==== Active Directory Authentication +Active Directory supports its own non-standard authentication options, and the normal usage pattern doesn't fit too cleanly with the standard `LdapAuthenticationProvider`. Typically authentication is performed using the domain username (in the form `user@domain`), rather than using an LDAP distinguished name. To make this easier, Spring Security 3.1 has an authentication provider which is customized for a typical Active Directory setup. + + +===== ActiveDirectoryLdapAuthenticationProvider +Configuring `ActiveDirectoryLdapAuthenticationProvider` is quite straightforward. You just need to supply the domain name and an LDAP URL supplying the address of the server footnote:[It is also possible to obtain the server's IP address using a DNS lookup. This is not currently supported, but hopefully will be in a future version.]. An example configuration would then look like this: + +[source,xml] +---- + + + + + +} +---- + +Note that there is no need to specify a separate `ContextSource` in order to define the server location - the bean is completely self-contained. A user named "Sharon", for example, would then be able to authenticate by entering either the username `sharon` or the full Active Directory `userPrincipalName`, namely `sharon@mydomain.com`. The user's directory entry will then be located, and the attributes returned for possible use in customizing the created `UserDetails` object (a `UserDetailsContextMapper` can be injected for this purpose, as described above). All interaction with the directory takes place with the identity of the user themselves. There is no concept of a "manager" user. + +By default, the user authorities are obtained from the `memberOf` attribute values of the user entry. The authorities allocated to the user can again be customized using a `UserDetailsContextMapper`. You can also inject a `GrantedAuthoritiesMapper` into the provider instance to control the authorities which end up in the `Authentication` object. + +====== Active Directory Error Codes +By default, a failed result will cause a standard Spring Security `BadCredentialsException`. If you set the property `convertSubErrorCodesToExceptions` to `true`, the exception messages will be parsed to attempt to extract the Active Directory-specific error code and raise a more specific exception. Check the class Javadoc for more information. + + +[[taglibs]] +=== JSP Tag Libraries +Spring Security has its own taglib which provides basic support for accessing security information and applying security constraints in JSPs. + + +==== Declaring the Taglib +To use any of the tags, you must have the security taglib declared in your JSP: + +[source,xml] +---- +<%@ taglib prefix="sec" uri="http://www.springframework.org/security/tags" %> +---- + +==== The authorize Tag +This tag is used to determine whether its contents should be evaluated or not. In Spring Security 3.0, it can be used in two ways footnote:[ +The legacy options from Spring Security 2.0 are also supported, but discouraged. +]. The first approach uses a <>, specified in the `access` attribute of the tag. The expression evaluation will be delegated to the `SecurityExpressionHandler` defined in the application context (you should have web expressions enabled in your `` namespace configuration to make sure this service is available). So, for example, you might have + +[source,xml] +---- + + + This content will only be visible to users who have the "supervisor" authority in their list of GrantedAuthoritys. + + +---- + +A common requirement is to only show a particular link, if the user is actually allowed to click it. How can we determine in advance whether something will be allowed? This tag can also operate in an alternative mode which allows you to define a particular URL as an attribute. If the user is allowed to invoke that URL, then the tag body will be evaluated, otherwise it will be skipped. So you might have something like + +[source,xml] +---- + + + This content will only be visible to users who are authorized to send requests to the "/admin" URL. + + +---- + +To use this tag there must also be an instance of `WebInvocationPrivilegeEvaluator` in your application context. If you are using the namespace, one will automatically be registered. This is an instance of `DefaultWebInvocationPrivilegeEvaluator`, which creates a dummy web request for the supplied URL and invokes the security interceptor to see whether the request would succeed or fail. This allows you to delegate to the access-control setup you defined using `intercept-url` declarations within the `` namespace configuration and saves having to duplicate the information (such as the required roles) within your JSPs. This approach can also be combined with a `method` attribute, supplying the HTTP method, for a more specific match. + +The boolean result of evaluating the tag (whether it grants or denies access) can be stored in a page context scope variable by setting the `var` attribute to the variable name, avoiding the need for duplicating and re-evaluating the condition at other points in the page. + + +===== Disabling Tag Authorization for Testing +Hiding a link in a page for unauthorized users doesn't prevent them from accessing the URL. They could just type it into their browser directly, for example. As part of your testing process, you may want to reveal the hidden areas in order to check that links really are secured at the back end. If you set the system property `spring.security.disableUISecurity` to `true`, the `authorize` tag will still run but will not hide its contents. By default it will also surround the content with `...` tags. This allows you to display "hidden" content with a particular CSS style such as a different background colour. Try running the "tutorial" sample application with this property enabled, for example. + +You can also set the properties `spring.security.securedUIPrefix` and `spring.security.securedUISuffix` if you want to change surrounding text from the default `span` tags (or use empty strings to remove it completely). + + +==== The authentication Tag +This tag allows access to the current `Authentication` object stored in the security context. It renders a property of the object directly in the JSP. So, for example, if the `principal` property of the `Authentication` is an instance of Spring Security's `UserDetails` object, then using `` will render the name of the current user. + +Of course, it isn't necessary to use JSP tags for this kind of thing and some people prefer to keep as little logic as possible in the view. You can access the `Authentication` object in your MVC controller (by calling `SecurityContextHolder.getContext().getAuthentication()`) and add the data directly to your model for rendering by the view. + + +==== The accesscontrollist Tag +This tag is only valid when used with Spring Security's ACL module. It checks a comma-separated list of required permissions for a specified domain object. If the current user has any of those permissions, then the tag body will be evaluated. If they don't, it will be skipped. An example might be + +[source,xml] +---- + + + This will be shown if the user has either of the permissions represented by the values "1" or "2" on the given object. + + +---- + +The permissions are passed to the `PermissionFactory` defined in the application context, converting them to ACL `Permission` instances, so they may be any format which is supported by the factory - they don't have to be integers, they could be strings like `READ` or `WRITE`. If no `PermissionFactory` is found, an instance of `DefaultPermissionFactory` will be used. The `AclService` from the application context will be used to load the `Acl` instance for the supplied object. The `Acl` will be invoked with the required permissions to check if any of them are granted. + +This tag also supports the `var` attribute, in the same way as the `authorize` tag. + + +[[jaas]] +=== Java Authentication and Authorization Service (JAAS) Provider + + +==== Overview +Spring Security provides a package able to delegate authentication requests to the Java Authentication and Authorization Service (JAAS). This package is discussed in detail below. + + +[[jaas-abstractjaasauthenticationprovider]] +==== AbstractJaasAuthenticationProvider +The `AbstractJaasAuthenticationProvider` is the basis for the provided JAAS `AuthenticationProvider` implementations. Subclasses must implement a method that creates the `LoginContext`. The `AbstractJaasAuthenticationProvider` has a number of dependencies that can be injected into it that are discussed below. + + +[[jaas-callbackhandler]] +===== JAAS CallbackHandler +Most JAAS `LoginModule` s require a callback of some sort. These callbacks are usually used to obtain the username and password from the user. + +In a Spring Security deployment, Spring Security is responsible for this user interaction (via the authentication mechanism). Thus, by the time the authentication request is delegated through to JAAS, Spring Security's authentication mechanism will already have fully-populated an `Authentication` object containing all the information required by the JAAS `LoginModule`. + +Therefore, the JAAS package for Spring Security provides two default callback handlers, `JaasNameCallbackHandler` and `JaasPasswordCallbackHandler`. Each of these callback handlers implement `JaasAuthenticationCallbackHandler`. In most cases these callback handlers can simply be used without understanding the internal mechanics. + +For those needing full control over the callback behavior, internally `AbstractJaasAuthenticationProvider` wraps these `JaasAuthenticationCallbackHandler` s with an `InternalCallbackHandler`. The `InternalCallbackHandler` is the class that actually implements JAAS’ normal `CallbackHandler` interface. Any time that the JAAS `LoginModule` is used, it is passed a list of application context configured `InternalCallbackHandler` s. If the `LoginModule` requests a callback against the `InternalCallbackHandler` s, the callback is in-turn passed to the `JaasAuthenticationCallbackHandler` s being wrapped. + + +[[jaas-authoritygranter]] +===== JAAS AuthorityGranter +JAAS works with principals. Even "roles" are represented as principals in JAAS. Spring Security, on the other hand, works with `Authentication` objects. Each `Authentication` object contains a single principal, and multiple `GrantedAuthority` s. To facilitate mapping between these different concepts, Spring Security's JAAS package includes an `AuthorityGranter` interface. + +An `AuthorityGranter` is responsible for inspecting a JAAS principal and returning a set of `String` s, representing the authorities assigned to the principal. For each returned authority string, the `AbstractJaasAuthenticationProvider` creates a `JaasGrantedAuthority` (which implements Spring Security’s `GrantedAuthority` interface) containing the authority string and the JAAS principal that the `AuthorityGranter` was passed. The `AbstractJaasAuthenticationProvider` obtains the JAAS principals by firstly successfully authenticating the user’s credentials using the JAAS `LoginModule`, and then accessing the `LoginContext` it returns. A call to `LoginContext.getSubject().getPrincipals()` is made, with each resulting principal passed to each `AuthorityGranter` defined against the `AbstractJaasAuthenticationProvider.setAuthorityGranters(List)` property. + +Spring Security does not include any production `AuthorityGranter` s given that every JAAS principal has an implementation-specific meaning. However, there is a `TestAuthorityGranter` in the unit tests that demonstrates a simple `AuthorityGranter` implementation. + + +[[jaas-defaultjaasauthenticationprovider]] +==== DefaultJaasAuthenticationProvider +The `DefaultJaasAuthenticationProvider` allows a JAAS `Configuration` object to be injected into it as a dependency. It then creates a `LoginContext` using the injected JAAS `Configuration`. This means that `DefaultJaasAuthenticationProvider` is not bound any particular implementation of `Configuration` as `JaasAuthenticationProvider` is. + + +[[jaas-inmemoryconfiguration]] +===== InMemoryConfiguration +In order to make it easy to inject a `Configuration` into `DefaultJaasAuthenticationProvider`, a default in memory implementation named `InMemoryConfiguration` is provided. The implementation constructor accepts a `Map` where each key represents a login configuration name and the value represents an `Array` of `AppConfigurationEntry` s. `InMemoryConfiguration` also supports a default `Array` of `AppConfigurationEntry` objects that will be used if no mapping is found within the provided `Map`. For details, refer to the class level javadoc of `InMemoryConfiguration`. + + +[[jaas-djap-config]] +===== DefaultJaasAuthenticationProvider Example Configuration +While the Spring configuration for `InMemoryConfiguration` can be more verbose than the standarad JAAS configuration files, using it in conjuction with `DefaultJaasAuthenticationProvider` is more flexible than `JaasAuthenticationProvider` since it not dependant on the default `Configuration` implementation. + +An example configuration of `DefaultJaasAuthenticationProvider` using `InMemoryConfiguration` is provided below. Note that custom implementations of `Configuration` can easily be injected into `DefaultJaasAuthenticationProvider` as well. + + +[source,xml] +---- + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +---- + + + +[[jaas-jaasauthenticationprovider]] +==== JaasAuthenticationProvider +The `JaasAuthenticationProvider` assumes the default `Configuration` is an instance of http://download.oracle.com/javase/1.4.2/docs/guide/security/jaas/spec/com/sun/security/auth/login/ConfigFile.html[ ConfigFile]. This assumption is made in order to attempt to update the `Configuration`. The `JaasAuthenticationProvider` then uses the default `Configuration` to create the `LoginContext`. + +Let’s assume we have a JAAS login configuration file, `/WEB-INF/login.conf`, with the following contents: + +[source,txt] +---- +JAASTest { + sample.SampleLoginModule required; +}; +---- + +Like all Spring Security beans, the `JaasAuthenticationProvider` is configured via the application context. The following definitions would correspond to the above JAAS login configuration file: + +[source,xml] +---- + + + + + + + + + + + + + + + + +---- + +[[jaas-apiprovision]] +==== Running as a Subject +If configured, the `JaasApiIntegrationFilter` will attempt to run as the `Subject` on the `JaasAuthenticationToken`. This means that the `Subject` can be accessed using: + +[source,java] +---- +Subject subject = Subject.getSubject(AccessController.getContext()); +---- + +This integration can easily be configured using the <> attribute. This feature is useful when integrating with legacy or external API's that rely on the JAAS Subject being populated. + +[[cas]] +=== CAS Authentication + +[[cas-overview]] +==== Overview +JA-SIG produces an enterprise-wide single sign on system known as CAS. Unlike other initiatives, JA-SIG's Central Authentication Service is open source, widely used, simple to understand, platform independent, and supports proxy capabilities. Spring Security fully supports CAS, and provides an easy migration path from single-application deployments of Spring Security through to multiple-application deployments secured by an enterprise-wide CAS server. + +You can learn more about CAS at http://www.ja-sig.org/cas. You will also need to visit this site to download the CAS Server files. + +[[cas-how-it-works]] +==== How CAS Works +Whilst the CAS web site contains documents that detail the architecture of CAS, we present the general overview again here within the context of Spring Security. Spring Security 3.x supports CAS 3. At the time of writing, the CAS server was at version 3.4. + +Somewhere in your enterprise you will need to setup a CAS server. The CAS server is simply a standard WAR file, so there isn't anything difficult about setting up your server. Inside the WAR file you will customise the login and other single sign on pages displayed to users. + +When deploying a CAS 3.4 server, you will also need to specify an `AuthenticationHandler` in the `deployerConfigContext.xml` included with CAS. The `AuthenticationHandler` has a simple method that returns a boolean as to whether a given set of Credentials is valid. Your `AuthenticationHandler` implementation will need to link into some type of backend authentication repository, such as an LDAP server or database. CAS itself includes numerous `AuthenticationHandler` s out of the box to assist with this. When you download and deploy the server war file, it is set up to successfully authenticate users who enter a password matching their username, which is useful for testing. + +Apart from the CAS server itself, the other key players are of course the secure web applications deployed throughout your enterprise. These web applications are known as "services". There are three types of services. Those that authenticate service tickets, those that can obtain proxy tickets, and those that authenticate proxy tickets. Authenticating a proxy ticket differs because the list of proxies must be validated and often times a proxy ticket can be reused. + + +[[cas-sequence]] +===== Spring Security and CAS Interaction Sequence +The basic interaction between a web browser, CAS server and a Spring Security-secured service is as follows: + +* The web user is browsing the service's public pages. CAS or Spring Security is not involved. +* The user eventually requests a page that is either secure or one of the beans it uses is secure. Spring Security's `ExceptionTranslationFilter` will detect the `AccessDeniedException` or `AuthenticationException`. +* Because the user's `Authentication` object (or lack thereof) caused an `AuthenticationException`, the `ExceptionTranslationFilter` will call the configured `AuthenticationEntryPoint`. If using CAS, this will be the `CasAuthenticationEntryPoint` class. +* The `CasAuthenticationEntryPoint` will redirect the user's browser to the CAS server. It will also indicate a `service` parameter, which is the callback URL for the Spring Security service (your application). For example, the URL to which the browser is redirected might be https://my.company.com/cas/login?service=https%3A%2F%2Fserver3.company.com%2Fwebapp%2Fj_spring_cas_security_check. +* After the user's browser redirects to CAS, they will be prompted for their username and password. If the user presents a session cookie which indicates they've previously logged on, they will not be prompted to login again (there is an exception to this procedure, which we'll cover later). CAS will use the `PasswordHandler` (or `AuthenticationHandler` if using CAS 3.0) discussed above to decide whether the username and password is valid. +* Upon successful login, CAS will redirect the user's browser back to the original service. It will also include a `ticket` parameter, which is an opaque string representing the "service ticket". Continuing our earlier example, the URL the browser is redirected to might be https://server3.company.com/webapp/j_spring_cas_security_check?ticket=ST-0-ER94xMJmn6pha35CQRoZ. +* Back in the service web application, the `CasAuthenticationFilter` is always listening for requests to `/j_spring_cas_security_check` (this is configurable, but we'll use the defaults in this introduction). The processing filter will construct a `UsernamePasswordAuthenticationToken` representing the service ticket. The principal will be equal to `CasAuthenticationFilter.CAS_STATEFUL_IDENTIFIER`, whilst the credentials will be the service ticket opaque value. This authentication request will then be handed to the configured `AuthenticationManager`. +* The `AuthenticationManager` implementation will be the `ProviderManager`, which is in turn configured with the `CasAuthenticationProvider`. The `CasAuthenticationProvider` only responds to `UsernamePasswordAuthenticationToken` s containing the CAS-specific principal (such as `CasAuthenticationFilter.CAS_STATEFUL_IDENTIFIER`) and `CasAuthenticationToken` s (discussed later). +* `CasAuthenticationProvider` will validate the service ticket using a `TicketValidator` implementation. This will typically be a `Cas20ServiceTicketValidator` which is one of the classes included in the CAS client library. In the event the application needs to validate proxy tickets, the `Cas20ProxyTicketValidator` is used. The `TicketValidator` makes an HTTPS request to the CAS server in order to validate the service ticket. It may also include a proxy callback URL, which is included in this example: https://my.company.com/cas/proxyValidate?service=https%3A%2F%2Fserver3.company.com%2Fwebapp%2Fj_spring_cas_security_check&ticket=ST-0-ER94xMJmn6pha35CQRoZ&pgtUrl=https://server3.company.com/webapp/j_spring_cas_security_proxyreceptor. +* Back on the CAS server, the validation request will be received. If the presented service ticket matches the service URL the ticket was issued to, CAS will provide an affirmative response in XML indicating the username. If any proxy was involved in the authentication (discussed below), the list of proxies is also included in the XML response. +* [OPTIONAL] If the request to the CAS validation service included the proxy callback URL (in the `pgtUrl` parameter), CAS will include a `pgtIou` string in the XML response. This `pgtIou` represents a proxy-granting ticket IOU. The CAS server will then create its own HTTPS connection back to the `pgtUrl`. This is to mutually authenticate the CAS server and the claimed service URL. The HTTPS connection will be used to send a proxy granting ticket to the original web application. For example, https://server3.company.com/webapp/j_spring_cas_security_proxyreceptor?pgtIou=PGTIOU-0-R0zlgrl4pdAQwBvJWO3vnNpevwqStbSGcq3vKB2SqSFFRnjPHt&pgtId=PGT-1-si9YkkHLrtACBo64rmsi3v2nf7cpCResXg5MpESZFArbaZiOKH. +* The `Cas20TicketValidator` will parse the XML received from the CAS server. It will return to the `CasAuthenticationProvider` a `TicketResponse`, which includes the username (mandatory), proxy list (if any were involved), and proxy-granting ticket IOU (if the proxy callback was requested). +* Next `CasAuthenticationProvider` will call a configured `CasProxyDecider`. The `CasProxyDecider` indicates whether the proxy list in the `TicketResponse` is acceptable to the service. Several implementations are provided with Spring Security: `RejectProxyTickets`, `AcceptAnyCasProxy` and `NamedCasProxyDecider`. These names are largely self-explanatory, except `NamedCasProxyDecider` which allows a `List` of trusted proxies to be provided. +* `CasAuthenticationProvider` will next request a `AuthenticationUserDetailsService` to load the `GrantedAuthority` objects that apply to the user contained in the `Assertion`. +* If there were no problems, `CasAuthenticationProvider` constructs a `CasAuthenticationToken` including the details contained in the `TicketResponse` and the `GrantedAuthority`s. +* Control then returns to `CasAuthenticationFilter`, which places the created `CasAuthenticationToken` in the security context. +* The user's browser is redirected to the original page that caused the `AuthenticationException` (or a <> depending on the configuration). + +It's good that you're still here! Let's now look at how this is configured + +[[cas-client]] +==== Configuration of CAS Client +The web application side of CAS is made easy due to Spring Security. It is assumed you already know the basics of using Spring Security, so these are not covered again below. We'll assume a namespace based configuration is being used and add in the CAS beans as required. Each section builds upon the previous section. A full<> can be found in the Spring Security Samples. + + +[[cas-st]] +===== Service Ticket Authentication +This section describes how to setup Spring Security to authenticate Service Tickets. Often times this is all a web application requires. You will need to add a `ServiceProperties` bean to your application context. This represents your CAS service: + +[source,xml] +---- + + + + +---- + +The `service` must equal a URL that will be monitored by the `CasAuthenticationFilter`. The `sendRenew` defaults to false, but should be set to true if your application is particularly sensitive. What this parameter does is tell the CAS login service that a single sign on login is unacceptable. Instead, the user will need to re-enter their username and password in order to gain access to the service. + +The following beans should be configured to commence the CAS authentication process (assuming you're using a namespace configuration): + +[source,xml] +---- + + ... + + + + + + + + + + + +---- + +For CAS to operate, the `ExceptionTranslationFilter` must have its `authenticationEntryPoint` property set to the `CasAuthenticationEntryPoint` bean. This can easily be done using <> as is done in the example above. The `CasAuthenticationEntryPoint` must refer to the `ServiceProperties` bean (discussed above), which provides the URL to the enterprise's CAS login server. This is where the user's browser will be redirected. + +The `CasAuthenticationFilter` has very similar properties to the `UsernamePasswordAuthenticationFilter` (used for form-based logins). You can use these properties to customize things like behavior for authentication success and failure. + +Next you need to add a `CasAuthenticationProvider` and its collaborators: + +[source,xml] +---- + + + + + + + + + + + + + + + + + + + + + + ... + +---- + +The `CasAuthenticationProvider` uses a `UserDetailsService` instance to load the authorities for a user, once they have been authenticated by CAS. We've shown a simple in-memory setup here. Note that the `CasAuthenticationProvider` does not actually use the password for authentication, but it does use the authorities. + +The beans are all reasonably self-explanatory if you refer back to the <> section. + +This completes the most basic configuration for CAS. If you haven't made any mistakes, your web application should happily work within the framework of CAS single sign on. No other parts of Spring Security need to be concerned about the fact CAS handled authentication. In the following sections we will discuss some (optional) more advanced configurations. + + +[[cas-singlelogout]] +===== Single Logout +The CAS protocol supports Single Logout and can be easily added to your Spring Security configuration. Below are updates to the Spring Security configuration that handle Single Logout + +[source,xml] +---- + + ... + + + + + + + + + + + + + + + + +---- + +The `logout` element logs the user out of the local application, but does not terminate the session with the CAS server or any other applications that have been logged into. The `requestSingleLogoutFilter` filter will allow the url of `/spring_security_cas_logout` to be requested to redirect the application to the configured CAS Server logout url. Then the CAS Server will send a Single Logout request to all the services that were signed into. The `singleLogoutFilter` handles the Single Logout request by looking up the `HttpSession` in a static `Map` and then invalidating it. + +It might be confusing why both the `logout` element and the `singleLogoutFilter` are needed. It is considered best practice to logout locally first since the `SingleSignOutFilter` just stores the `HttpSession` in a static `Map` in order to call invalidate on it. With the configuration above, the flow of logout would be: + +* The user requests `/j_spring_security_logout` which would log the user out of the local application and send the user to the logout success page. +* The logout success page, `/cas-logout.jsp`, should instruct the user to click a link pointing to `/j_spring_cas_security_logout` in order to logout out of all applications. +* When the user clicks the link, the user is redirected to the CAS single logout URL (https://localhost:9443/cas/logout). +* On the CAS Server side, the CAS single logout URL then submits single logout requests to all the CAS Services. On the CAS Service side, JASIG's `SingleSignOutFilter` processes the logout request by invaliditing the original session. + + + +The next step is to add the following to your web.xml + +[source,xml] +---- + + characterEncodingFilter + + org.springframework.web.filter.CharacterEncodingFilter + + + encoding + UTF-8 + + + + characterEncodingFilter + /* + + + + org.jasig.cas.client.session.SingleSignOutHttpSessionListener + + +---- + +When using the SingleSignOutFilter you might encounter some encoding issues. Therefore it is recommended to add the `CharacterEncodingFilter` to ensure that the character encoding is correct when using the `SingleSignOutFilter`. Again, refer to JASIG's documentation for details. The `SingleSignOutHttpSessionListener` ensures that when an `HttpSession` expires, the mapping used for single logout is removed. + + +[[cas-pt-client]] +===== Authenticating to a Stateless Service with CAS +This section describes how to authenticate to a service using CAS. In other words, this section discusses how to setup a client that uses a service that authenticates with CAS. The next section describes how to setup a stateless service to Authenticate using CAS. + + +[[cas-pt-client-config]] +====== Configuring CAS to Obtain Proxy Granting Tickets +In order to authenticate to a stateless service, the application needs to obtain a proxy granting ticket (PGT). This section describes how to configure Spring Security to obtain a PGT building upon thencas-st[Service Ticket Authentication] configuration. + +The first step is to include a `ProxyGrantingTicketStorage` in your Spring Security configuration. This is used to store PGT's that are obtained by the `CasAuthenticationFilter` so that they can be used to obtain proxy tickets. An example configuration is shown below + +[source,xml] +---- + + +---- + +The next step is to update the `CasAuthenticationProvider` to be able to obtain proxy tickets. To do this replace the `Cas20ServiceTicketValidator` with a `Cas20ProxyTicketValidator`. The `proxyCallbackUrl` should be set to a URL that the application will receive PGT's at. Last, the configuration should also reference the `ProxyGrantingTicketStorage` so it can use a PGT to obtain proxy tickets. You can find an example of the configuration changes that should be made below. + +[source,xml] +---- + + ... + + + + + + + + +---- + +The last step is to update the `CasAuthenticationFilter` to accept PGT and to store them in the `ProxyGrantingTicketStorage`. It is important the the `proxyReceptorUrl` matches the `proxyCallbackUrl` of the `Cas20ProxyTicketValidator`. An example configuration is shown below. + +[source,xml] +---- + + + ... + + + + +---- + +[[cas-pt-client-sample]] +====== Calling a Stateless Service Using a Proxy Ticket +Now that Spring Security obtains PGTs, you can use them to create proxy tickets which can be used to authenticate to a stateless service. The <> contains a working example in the `ProxyTicketSampleServlet`. Example code can be found below: + +[source,java] +---- +protected void doGet(HttpServletRequest request, HttpServletResponse response) + throws ServletException, IOException { + // NOTE: The CasAuthenticationToken can also be obtained using + // SecurityContextHolder.getContext().getAuthentication() + final CasAuthenticationToken token = (CasAuthenticationToken) request.getUserPrincipal(); + // proxyTicket could be reused to make calls to the CAS service even if the + // target url differs + final String proxyTicket = token.getAssertion().getPrincipal().getProxyTicketFor(targetUrl); + + // Make a remote call using the proxy ticket + final String serviceUrl = targetUrl+"?ticket="+URLEncoder.encode(proxyTicket, "UTF-8"); + String proxyResponse = CommonUtils.getResponseFromServer(serviceUrl, "UTF-8"); + ... +} +---- + +[[cas-pt]] +===== Proxy Ticket Authentication +The `CasAuthenticationProvider` distinguishes between stateful and stateless clients. A stateful client is considered any that submits to the `filterProcessUrl` of the `CasAuthenticationFilter`. A stateless client is any that presents an authentication request to `CasAuthenticationFilter` on a URL other than the `filterProcessUrl`. + +Because remoting protocols have no way of presenting themselves within the context of an `HttpSession`, it isn't possible to rely on the default practice of storing the security context in the session between requests. Furthermore, because the CAS server invalidates a ticket after it has been validated by the `TicketValidator`, presenting the same proxy ticket on subsequent requests will not work. + +One obvious option is to not use CAS at all for remoting protocol clients. However, this would eliminate many of the desirable features of CAS. As a middle-ground, the `CasAuthenticationProvider` uses a `StatelessTicketCache`. This is used solely for stateless clients which use a principal equal to `CasAuthenticationFilter.CAS_STATELESS_IDENTIFIER`. What happens is the `CasAuthenticationProvider` will store the resulting `CasAuthenticationToken` in the `StatelessTicketCache`, keyed on the proxy ticket. Accordingly, remoting protocol clients can present the same proxy ticket and the `CasAuthenticationProvider` will not need to contact the CAS server for validation (aside from the first request). Once authenticated, the proxy ticket could be used for URLs other than the original target service. + +This section builds upon the previous sections to accomodate proxy ticket authentication. The first step is to specify to authenticate all artifacts as shown below. + +[source,xml] +---- + + ... + + +---- + +The next step is to specify `serviceProperties` and the `authenticationDetailsSource` for the `CasAuthenticationFilter`. The `serviceProperties` property instructs the `CasAuthenticationFilter` to attempt to authenticate all artifacts instead of only ones present on the `filterProcessUrl`. The `ServiceAuthenticationDetailsSource` creates a `ServiceAuthenticationDetails` that ensures the current URL, based upon the `HttpServletRequest`, is used as the service URL when validating the ticket. The method for generating the service URL can be customized by injecting a custom `AuthenticationDetailsSource` that returns a custom `ServiceAuthenticationDetails`. + +[source,xml] +---- + + ... + + + + + +---- + +You will also need to update the `CasAuthenticationProvider` to handle proxy tickets. To do this replace the `Cas20ServiceTicketValidator` with a `Cas20ProxyTicketValidator`. You will need to configure the `statelessTicketCache` and which proxies you want to accept. You can find an example of the updates required to accept all proxies below. + +[source,xml] +---- + + + ... + + + + + + + + + + + + + + + + + + + + + +---- + +[[x509]] +=== X.509 Authentication + + +[[x509-overview]] +==== Overview +The most common use of X.509 certificate authentication is in verifying the identity of a server when using SSL, most commonly when using HTTPS from a browser. The browser will automatically check that the certificate presented by a server has been issued (ie digitally signed) by one of a list of trusted certificate authorities which it maintains. + +You can also use SSL with "mutual authentication"; the server will then request a valid certificate from the client as part of the SSL handshake. The server will authenticate the client by checking that its certificate is signed by an acceptable authority. If a valid certificate has been provided, it can be obtained through the servlet API in an application. Spring Security X.509 module extracts the certificate using a filter. It maps the certificate to an application user and loads that user's set of granted authorities for use with the standard Spring Security infrastructure. + +You should be familiar with using certificates and setting up client authentication for your servlet container before attempting to use it with Spring Security. Most of the work is in creating and installing suitable certificates and keys. For example, if you're using Tomcat then read the instructions here http://tomcat.apache.org/tomcat-6.0-doc/ssl-howto.html[http://tomcat.apache.org/tomcat-6.0-doc/ssl-howto.html]. It's important that you get this working before trying it out with Spring Security + + +==== Adding X.509 Authentication to Your Web Application +Enabling X.509 client authentication is very straightforward. Just add the `` element to your http security namespace configuration. + +[source,xml] +---- + + ... + ; + +---- + +The element has two optional attributes: + +* `subject-principal-regex`. The regular expression used to extract a username from the certificate's subject name. The default value is shown above. This is the username which will be passed to the `UserDetailsService` to load the authorities for the user. +* `user-service-ref`. This is the bean Id of the `UserDetailsService` to be used with X.509. It isn't needed if there is only one defined in your application context. + + The `subject-principal-regex` should contain a single group. For example the default expression "CN=(.*?)," matches the common name field. So if the subject name in the certificate is "CN=Jimi Hendrix, OU=...", this will give a user name of "Jimi Hendrix". The matches are case insensitive. So "emailAddress=(.?)," will match "EMAILADDRESS=jimi@hendrix.org,CN=..." giving a user name "jimi@hendrix.org". If the client presents a certificate and a valid username is successfully extracted, then there should be a valid `Authentication` object in the security context. If no certificate is found, or no corresponding user could be found then the security context will remain empty. This means that you can easily use X.509 authentication with other options such as a form-based login. + +[[x509-ssl-config]] +==== Setting up SSL in Tomcat +There are some pre-generated certificates in the `samples/certificate` directory in the Spring Security project. You can use these to enable SSL for testing if you don't want to generate your own. The file `server.jks` contains the server certificate, private key and the issuing certificate authority certificate. There are also some client certificate files for the users from the sample applications. You can install these in your browser to enable SSL client authentication. + +To run tomcat with SSL support, drop the `server.jks` file into the tomcat `conf` directory and add the following connector to the `server.xml` file + +[source,xml] +---- + + + +---- + +`clientAuth` can also be set to `want` if you still want SSL connections to succeed even if the client doesn't provide a certificate. Clients which don't present a certificate won't be able to access any objects secured by Spring Security unless you use a non-X.509 authentication mechanism, such as form authentication. + + +[[runas]] +=== Run-As Authentication Replacement + +[[runas-overview]] +==== Overview +The `AbstractSecurityInterceptor` is able to temporarily replace the `Authentication` object in the `SecurityContext` and `SecurityContextHolder` during the secure object callback phase. This only occurs if the original `Authentication` object was successfully processed by the `AuthenticationManager` and `AccessDecisionManager`. The `RunAsManager` will indicate the replacement `Authentication` object, if any, that should be used during the `SecurityInterceptorCallback`. + +By temporarily replacing the `Authentication` object during the secure object callback phase, the secured invocation will be able to call other objects which require different authentication and authorization credentials. It will also be able to perform any internal security checks for specific `GrantedAuthority` objects. Because Spring Security provides a number of helper classes that automatically configure remoting protocols based on the contents of the `SecurityContextHolder`, these run-as replacements are particularly useful when calling remote web services + +[[runas-config]] +==== Configuration +A `RunAsManager` interface is provided by Spring Security: + +[source,java] +---- +Authentication buildRunAs(Authentication authentication, Object object, + List config); + +boolean supports(ConfigAttribute attribute); + +boolean supports(Class clazz); +---- + + + +The first method returns the `Authentication` object that should replace the existing `Authentication` object for the duration of the method invocation. If the method returns `null`, it indicates no replacement should be made. The second method is used by the `AbstractSecurityInterceptor` as part of its startup validation of configuration attributes. The `supports(Class)` method is called by a security interceptor implementation to ensure the configured `RunAsManager` supports the type of secure object that the security interceptor will present. + +One concrete implementation of a `RunAsManager` is provided with Spring Security. The `RunAsManagerImpl` class returns a replacement `RunAsUserToken` if any `ConfigAttribute` starts with `RUN_AS_`. If any such `ConfigAttribute` is found, the replacement `RunAsUserToken` will contain the same principal, credentials and granted authorities as the original `Authentication` object, along with a new `GrantedAuthorityImpl` for each `RUN_AS_` `ConfigAttribute`. Each new `GrantedAuthorityImpl` will be prefixed with `ROLE_`, followed by the `RUN_AS` `ConfigAttribute`. For example, a `RUN_AS_SERVER` will result in the replacement `RunAsUserToken` containing a `ROLE_RUN_AS_SERVER` granted authority. + +The replacement `RunAsUserToken` is just like any other `Authentication` object. It needs to be authenticated by the `AuthenticationManager`, probably via delegation to a suitable `AuthenticationProvider`. The `RunAsImplAuthenticationProvider` performs such authentication. It simply accepts as valid any `RunAsUserToken` presented. + +To ensure malicious code does not create a `RunAsUserToken` and present it for guaranteed acceptance by the `RunAsImplAuthenticationProvider`, the hash of a key is stored in all generated tokens. The `RunAsManagerImpl` and `RunAsImplAuthenticationProvider` is created in the bean context with the same key: + +[source,xml] +---- + + + + + + + + +---- + + + +By using the same key, each `RunAsUserToken` can be validated it was created by an approved `RunAsManagerImpl`. The `RunAsUserToken` is immutable after creation for security reasons + + +[[crypto]] +=== Spring Security Crypto Module + + +[[spring-security-crypto-introduction]] +==== Introduction +The Spring Security Crypto module provides support for symmetric encryption, key generation, and password encoding. The code is distributed as part of the core module but has no dependencies on any other Spring Security (or Spring) code. + + +[[spring-security-crypto-encryption]] +==== Encryptors +The Encryptors class provides factory methods for constructing symmetric encryptors. Using this class, you can create ByteEncryptors to encrypt data in raw byte[] form. You can also construct TextEncryptors to encrypt text strings. Encryptors are thread safe. + +[[spring-security-crypto-encryption-bytes]] +===== BytesEncryptor +Use the Encryptors.standard factory method to construct a "standard" BytesEncryptor: + +[source,java] +---- +Encryptors.standard("password", "salt"); +---- + +The "standard" encryption method is 256-bit AES using PKCS #5's PBKDF2 (Password-Based Key Derivation Function #2). This method requires Java 6. The password used to generate the SecretKey should be kept in a secure place and not be shared. The salt is used to prevent dictionary attacks against the key in the event your encrypted data is compromised. A 16-byte random initialization vector is also applied so each encrypted message is unique. + +The provided salt should be in hex-encoded String form, be random, and be at least 8 bytes in length. Such a salt may be generated using a KeyGenerator: + +[source,java] +---- +String salt = KeyGenerators.string().generateKey(); // generates a random 8-byte salt that is then hex-encoded +---- + +[[spring-security-crypto-encryption-text]] +===== TextEncryptor +Use the Encryptors.text factory method to construct a standard TextEncryptor: + +[source,java] +---- + +Encryptors.text("password", "salt"); +---- + +A TextEncryptor uses a standard BytesEncryptor to encrypt text data. Encrypted results are returned as hex-encoded strings for easy storage on the filesystem or in the database. + +Use the Encryptors.queryableText factory method to construct a "queryable" TextEncryptor: + +[source,java] +---- +Encryptors.queryableText("password", "salt"); +---- + +The difference between a queryable TextEncryptor and a standard TextEncryptor has to do with initialization vector (iv) handling. The iv used in a queryable TextEncryptor#encrypt operation is shared, or constant, and is not randomly generated. This means the same text encrypted multiple times will always produce the same encryption result. This is less secure, but necessary for encrypted data that needs to be queried against. An example of queryable encrypted text would be an OAuth apiKey. + +[[spring-security-crypto-keygenerators]] +==== Key Generators +The KeyGenerators class provides a number of convenience factory methods for constructing different types of key generators. Using this class, you can create a BytesKeyGenerator to generate byte[] keys. You can also construct a StringKeyGenerator to generate string keys. KeyGenerators are thread safe. + +===== BytesKeyGenerator +Use the KeyGenerators.secureRandom factory methods to generate a BytesKeyGenerator backed by a SecureRandom instance: + +[source,java] +---- +KeyGenerator generator = KeyGenerators.secureRandom(); +byte[] key = generator.generateKey(); +---- + +The default key length is 8 bytes. There is also a KeyGenerators.secureRandom variant that provides control over the key length: + +[source,java] +---- +KeyGenerators.secureRandom(16); +---- + +Use the KeyGenerators.shared factory method to construct a BytesKeyGenerator that always returns the same key on every invocation: + +[source,java] +---- +KeyGenerators.shared(16); +---- + +===== StringKeyGenerator +Use the KeyGenerators.string factory method to construct a 8-byte, SecureRandom KeyGenerator that hex-encodes each key as a String: + +[source,java] +---- +KeyGenerators.string(); +---- + +[[spring-security-crypto-passwordencoders]] +==== Password Encoding +The password package of the spring-security-crypto module provides support for encoding passwords. `PasswordEncoder` is the central service interface and has the following signature: + +[source,java] +---- +public interface PasswordEncoder { + + String encode(String rawPassword); + + boolean matches(String rawPassword, String encodedPassword); +} +---- + +The matches method returns true if the rawPassword, once encoded, equals the encodedPassword. This method is designed to support password-based authentication schemes. + +The `BCryptPasswordEncoder` implementation uses the widely supported "bcrypt" algorithm to hash the passwords. Bcrypt uses a random 16 byte salt value and is a deliberately slow algorithm, in order to hinder password crackers. The amount of work it does can be tuned using the "strength" parameter which takes values from 4 to 31. The higher the value, the more work has to be done to calculate the hash. The default value is 10. You can change this value in your deployed system without affecting existing passwords, as the value is also stored in the encoded hash. + +[source,java] +---- + +// Create an encoder with strength 16 +BCryptPasswordEncoder encoder = new BCryptPasswordEncoder(16); +String result = encoder.encode("myPassword"); +assertTrue(encoder.matches("myPassword", result)); +---- + +== Appendix + +[[appendix-schema]] +=== Security Database Schema +There are various database schema used by the framework and this appendix provides a single reference point to them all. You only need to provide the tables for the areas of functonality you require. + +DDL statements are given for the HSQLDB database. You can use these as a guideline for defining the schema for the database you are using. + + +==== User Schema +The standard JDBC implementation of the `UserDetailsService` (`JdbcDaoImpl`) requires tables to load the password, account status (enabled or disabled) and a list of authorities (roles) for the user. + +[source] +---- + +create table users( + username varchar_ignorecase(50) not null primary key, + password varchar_ignorecase(50) not null, + enabled boolean not null); + +create table authorities ( + username varchar_ignorecase(50) not null, + authority varchar_ignorecase(50) not null, + constraint fk_authorities_users foreign key(username) references users(username)); + create unique index ix_auth_username on authorities (username,authority); +---- + +===== Group Authorities +Spring Security 2.0 introduced support for group authorities in `JdbcDaoImpl`. The table structure if groups are enabled is as follows: + +[source] +---- + +create table groups ( + id bigint generated by default as identity(start with 0) primary key, + group_name varchar_ignorecase(50) not null); + +create table group_authorities ( + group_id bigint not null, + authority varchar(50) not null, + constraint fk_group_authorities_group foreign key(group_id) references groups(id)); + +create table group_members ( + id bigint generated by default as identity(start with 0) primary key, + username varchar(50) not null, + group_id bigint not null, + constraint fk_group_members_group foreign key(group_id) references groups(id)); +---- + +Remember that these tables are only required if you are using the provided JDBC `UserDetailsService` implementation. If you write your own or choose to implement `AuthenticationProvider` without a `UserDetailsService`, then you have complete freedom over how you store the data, as long as the interface contract is satisfied. + + +==== Persistent Login (Remember-Me) Schema +This table is used to store data used by the more secure <> remember-me implementation. If you are using `JdbcTokenRepositoryImpl` either directly or through the namespace, then you will need this table. + +[source] +---- + +create table persistent_logins ( + username varchar(64) not null, + series varchar(64) primary key, + token varchar(64) not null, + last_used timestamp not null); + +---- + +[[dbschema-acl]] +==== ACL Schema +There are four tables used by the Spring Security <> implementation. + +. `acl_sid` stores the security identities recognised by the ACL system. These can be unique principals or authorities which may apply to multiple principals. +. `acl_class` defines the domain object types to which ACLs apply. The `class` column stores the Java class name of the object. +. `acl_object_identity` stores the object identity definitions of specific domai objects. +. `acl_entry` stores the ACL permissions which apply to a specific object identity and security identity. + +It is assumed that the database will auto-generate the primary keys for each of the identities. The `JdbcMutableAclService` has to be able to retrieve these when it has created a new row in the `acl_sid` or `acl_class` tables. It has two properties which define the SQL needed to retrieve these values `classIdentityQuery` and `sidIdentityQuery`. Both of these default to `call identity()` + +===== Hypersonic SQL +The default schema works with the embedded HSQLDB database that is used in unit tests within the framework. + +[source] +---- + +create table acl_sid ( + id bigint generated by default as identity(start with 100) not null primary key, + principal boolean not null, + sid varchar_ignorecase(100) not null, + constraint unique_uk_1 unique(sid,principal) ); + +create table acl_class ( + id bigint generated by default as identity(start with 100) not null primary key, + class varchar_ignorecase(100) not null, + constraint unique_uk_2 unique(class) ); + +create table acl_object_identity ( + id bigint generated by default as identity(start with 100) not null primary key, + object_id_class bigint not null, + object_id_identity bigint not null, + parent_object bigint, + owner_sid bigint not null, + entries_inheriting boolean not null, + constraint unique_uk_3 unique(object_id_class,object_id_identity), + constraint foreign_fk_1 foreign key(parent_object)references acl_object_identity(id), + constraint foreign_fk_2 foreign key(object_id_class)references acl_class(id), + constraint foreign_fk_3 foreign key(owner_sid)references acl_sid(id) ); + +create table acl_entry ( + id bigint generated by default as identity(start with 100) not null primary key, + acl_object_identity bigint not null,ace_order int not null,sid bigint not null, + mask integer not null,granting boolean not null,audit_success boolean not null, + audit_failure boolean not null, + constraint unique_uk_4 unique(acl_object_identity,ace_order), + constraint foreign_fk_4 foreign key(acl_object_identity) + references acl_object_identity(id), + constraint foreign_fk_5 foreign key(sid) references acl_sid(id) ); +---- + +===== PostgreSQL +[source,ddl] +---- +create table acl_sid( + id bigserial not null primary key, + principal boolean not null, + sid varchar(100) not null, + constraint unique_uk_1 unique(sid,principal)); + +create table acl_class( + id bigserial not null primary key, + class varchar(100) not null, + constraint unique_uk_2 unique(class)); + +create table acl_object_identity( + id bigserial primary key, + object_id_class bigint not null, + object_id_identity bigint not null, + parent_object bigint, + owner_sid bigint, + entries_inheriting boolean not null, + constraint unique_uk_3 unique(object_id_class,object_id_identity), + constraint foreign_fk_1 foreign key(parent_object) references acl_object_identity(id), + constraint foreign_fk_2 foreign key(object_id_class) references acl_class(id), + constraint foreign_fk_3 foreign key(owner_sid) references acl_sid(id)); + +create table acl_entry( + id bigserial primary key, + acl_object_identity bigint not null, + ace_order int not null, + sid bigint not null, + mask integer not null, + granting boolean not null, + audit_success boolean not null, + audit_failure boolean not null, + constraint unique_uk_4 unique(acl_object_identity,ace_order), + constraint foreign_fk_4 foreign key(acl_object_identity) + references acl_object_identity(id), + constraint foreign_fk_5 foreign key(sid) references acl_sid(id)); +---- + +You will have to set the `classIdentityQuery` and `sidIdentityQuery` properties of `JdbcMutableAclService` to the following values, respectively: + +* `select currval(pg_get_serial_sequence('acl_class', 'id'))` +* `select currval(pg_get_serial_sequence('acl_sid', 'id'))` + +[[appendix-namespace]] +=== The Security Namespace +This appendix provides a reference to the elements available in the security namespace and information on the underlying beans they create (a knowledge of the individual classes and how they work together is assumed - you can find more information in the project Javadoc and elsewhere in this document). If you haven't used the namespace before, please read the <> on namespace configuration, as this is intended as a supplement to the information there. Using a good quality XML editor while editing a configuration based on the schema is recommended as this will provide contextual information on which elements and attributes are available as well as comments explaining their purpose. The namespace is written in http://www.relaxng.org/[RELAX NG] Compact format and later converted into an XSD schema. If you are familiar with this format, you may wish to examine the https://fisheye.springsource.org/browse/spring-security/config/src/main/resources/org/springframework/security/config/spring-security-3.2.rnc[schema file] directly. + +[[nsa-web]] +==== Web Application Security + +[[nsa-debug]] +===== +Enables Spring Security debugging infrastructure. This will provide human-readable (multi-line) debugging information to monitor requests coming into the security filters. This may include sensitive information, such as request parameters or headers, and should only be used in a development environment. + +[[nsa-http]] +===== +If you use an `` element within your application, a `FilterChainProxy` bean named "springSecurityFilterChain" is created and the configuration within the element is used to build a filter chain within `FilterChainProxy`. As of Spring Security 3.1, additional `http` elements can be used to add extra filter chains footnote:[ +See the <> for how to set up the mapping from your `web.xml` +]. Some core filters are always created in a filter chain and others will be added to the stack depending on the attributes and child elements which are present. The positions of the standard filters are fixed (see <> in the namespace introduction), removing a common source of errors with previous versions of the framework when users had to configure the filter chain explicitly in the `FilterChainProxy` bean. You can, of course, still do this if you need full control of the configuration. + +All filters which require a reference to the `AuthenticationManager` will be automatically injected with the internal instance created by the namespace configuration (see the <> for more on the `AuthenticationManager`). + +Each `` namespace block always creates an `SecurityContextPersistenceFilter`, an `ExceptionTranslationFilter` and a `FilterSecurityInterceptor`. These are fixed and cannot be replaced with alternatives. + + +[[nsa-http-attributes]] +====== Attributes +The attributes on the `` element control some of the properties on the core filters. + + +[[nsa-http-access-decision-manager-ref]] +* **access-decision-manager-ref** +Optional attribute specifying the ID of the `AccessDecisionManager` implementation which should be used for authorizing HTTP requests. By default an `AffirmativeBased` implementation is used for with a `RoleVoter` and an `AuthenticatedVoter`. + + +[[nsa-http-access-denied-page]] +* **access-denied-page** +Deprecated in favour of the <> child element. + + +[[nsa-http-authentication-manager-ref]] +* **authentication-manager-ref** +A reference to the `AuthenticationManager` used for the `FilterChain` created by this http element. + + +[[nsa-http-auto-config]] +* **auto-config** +Automatically registers a login form, BASIC authentication, logout services. If set to "true", all of these capabilities are added (although you can still customize the configuration of each by providing the respective element). If unspecified, defaults to "false". Use of this attribute is not recommended. Use explicit configuration elements instead to avoid confusion. + + +[[nsa-http-create-session]] +* **create-session** +Controls the eagerness with which an HTTP session is created by Spring Security classes. Options include: + +** `always` - Spring Security will proactively create a session if one does not exist. +** `ifRequired` - Spring Security will only create a session only if one is required (default value). +** `never` - Spring Security will never create a session, but will make use of one if the application does. +** `stateless` - Spring Security will not create a session and ignore the session for obtaining a Spring `Authentication`. + +[[nsa-http-disable-url-rewriting]] +* **disable-url-rewriting** +Prevents session IDs from being appended to URLs in the application. Clients must use cookies if this attribute is set to `true`. The default is `false`. + + +[[nsa-http-entry-point-ref]] +* **entry-point-ref** +Normally the `AuthenticationEntryPoint` used will be set depending on which authentication mechanisms have been configured. This attribute allows this behaviour to be overridden by defining a customized `AuthenticationEntryPoint` bean which will start the authentication process. + + +[[nsa-http-jaas-api-provision]] +* **jaas-api-provision** +If available, runs the request as the `Subject` acquired from the `JaasAuthenticationToken` which is implemented by adding a `JaasApiIntegrationFilter` bean to the stack. Defaults to `false`. + + +[[nsa-http-name]] +* **name** +A bean identifier, used for referring to the bean elsewhere in the context. + + +[[nsa-http-once-per-request]] +* **once-per-request** +Corresponds to the `observeOncePerRequest` property of `FilterSecurityInterceptor`. Defaults to `true`. + + +[[nsa-http-path-type]] +* **path-type** +Deprecated in favor of <>. + + +[[nsa-http-pattern]] +* **pattern** +Defining a pattern for the <> element controls the requests which will be filtered through the list of filters which it defines. The interpretation is dependent on the configured <>. If no pattern is defined, all requests will be matched, so the most specific patterns should be declared first. + + +[[nsa-http-realm]] +* **realm** +Sets the realm name used for basic authentication (if enabled). Corresponds to the `realmName` property on `BasicAuthenticationEntryPoint`. + + +[[nsa-http-request-matcher]] +* **request-matcher** +Defines the `RequestMatcher` strategy used in the `FilterChainProxy` and the beans created by the `intercept-url` to match incoming requests. Options are currently `ant`, `regex` and `ciRegex`, for ant, regular-expression and case-insensitive regular-expression repsectively. A separate instance is created for each<> element using its <> and <> attributes. Ant paths are matched using an `AntPathRequestMatcher` and regular expressions are matched using a `RegexRequestMatcher`. See the Javadoc for these classes for more details on exactly how the matching is preformed. Ant paths are the default strategy. + + +[[nsa-http-request-matcher-ref]] +* **request-matcher-ref** +A referenece to a bean that implements `RequestMatcher` that will determine if this `FilterChain` should be used. This is a more powerful alternative to <>. + + +[[nsa-http-security]] +* **security** +A request pattern can be mapped to an empty filter chain, by setting this attribute to `none`. No security will be applied and none of Spring Security's features will be available. + + +[[nsa-http-security-context-repository-ref]] +* **security-context-repository-ref** +Allows injection of a custom `SecurityContextRepository` into the `SecurityContextPersistenceFilter`. + + +[[nsa-http-servlet-api-provision]] +* **servlet-api-provision** +Provides versions of `HttpServletRequest` security methods such as `isUserInRole()` and `getPrincipal()` which are implemented by adding a `SecurityContextHolderAwareRequestFilter` bean to the stack. Defaults to `true`. + + +[[nsa-http-use-expressions]] +* **use-expressions** +Enables EL-expressions in the `access` attribute, as described in the chapter on <>. + + +[[nsa-http-children]] +====== Child Elements of +* <> +* <> +* <> +* <> +* <> +* <> +* <> +* <> +* <> +* <> +* <> +* <> +* <> +* <> +* <> +* <> +* <> + + +[[nsa-access-denied-handler]] +===== +This element allows you to set the `errorPage` property for the default `AccessDeniedHandler` used by the `ExceptionTranslationFilter`, using the <> attribute, or to supply your own implementation using the<> attribute. This is discussed in more detail in the section on the <>. + + +[[nsa-access-denied-handler-parents]] +====== Parent Elements of + +* <> + +[[nsa-access-denied-handler-attributes]] +====== Attributes + + +[[nsa-access-denied-handler-error-page]] +* **error-page** +The access denied page that an authenticated user will be redirected to if they request a page which they don't have the authority to access. + + +[[nsa-access-denied-handler-ref]] +* **ref** +Defines a reference to a Spring bean of type `AccessDeniedHandler `. + + +[[nsa-headers]] +===== +This element allows for configuring additional (security) headers to be send with the response. It enables easy configuration for several headers and also allows for setting custom headers through the <> element. Additional information, can be found in the <> section of the reference. + +** `Cache-Control`, `Pragma`, and `Expires` - Can be set using the <> element. This ensures that the browser does not cache your secured pages. +** `Strict-Transport-Security` - Can be set using the <> element. This ensures that the browser automatically requests HTTPS for future requests. +** `X-Frame-Options` - Can be set using the <> element. The http://en.wikipedia.org/wiki/Clickjacking#X-Frame-Options[X-Frame-Options ] header can be used to prevent clickjacking attacks. +** `X-XSS-Protection` - Can be set using the <> element. The http://en.wikipedia.org/wiki/Cross-site_scripting[X-XSS-Protection ] header can be used by browser to do basic control. +** `X-Content-Type-Options` - Can be set using the <> element. The http://blogs.msdn.com/b/ie/archive/2008/09/02/ie8-security-part-vi-beta-2-update.aspx[X-Content-Type-Options] header prevents Internet Explorer from MIME-sniffing a response away from the declared content-type. This also applies to Google Chrome, when downloading extensions. + + + + +[[nsa-headers-parents]] +====== Parent Elements of + +* <> + + + +[[nsa-headers-children]] +====== Child Elements of + + +* <> +* <> +* <> +* <> +* <> +* <> + + + +[[nsa-cache-control]] +===== +Adds `Cache-Control`, `Pragma`, and `Expires` headers to ensure that the browser does not cache your secured pages. + + +[[nsa-cache-control-parents]] +====== Parent Elements of + + +* <> + + + +[[nsa-hsts]] +===== +When enabled adds the http://tools.ietf.org/html/rfc6797[Strict-Transport-Security] header to the response for any secure request. This allows the server to instruct browsers to automatically use HTTPS for future requests. + + +[[nsa-hsts-attributes]] +====== Attributes + + +[[nsa-hsts-include-subdomains]] +* **include-sub-domains** +Specifies if subdomains should be included. Default true. + + +[[nsa-hsts-max-age-seconds]] +* **max-age-seconds** +Specifies the maximum ammount of time the host should be considered a Known HSTS Host. Default one year. + + +[[nsa-hsts-request-matcher-ref]] +* **request-matcher-ref** +The RequestMatcher instance to be used to determine if the header should be set. Default is if HttpServletRequest.isSecure() is true. + + +[[nsa-hsts-parents]] +====== Parent Elements of + +* <> + + + +[[nsa-frame-options]] +===== +When enabled adds the http://tools.ietf.org/html/draft-ietf-websec-x-frame-options[X-Frame-Options header] to the response, this allows newer browsers to do some security checks and prevent http://en.wikipedia.org/wiki/Clickjacking[clickjacking] attacks. + + +[[nsa-frame-options-attributes]] +====== Attributes + + +[[nsa-frame-options-policy]] +* **policy** +** `DENY` The page cannot be displayed in a frame, regardless of the site attempting to do so. This is the default when frame-options-policy is specified. +** `SAMEORIGIN` The page can only be displayed in a frame on the same origin as the page itself +** `ALLOW-FROM` <> The page can only be displayed in a frame on the specified origin. + ++ + +In other words, if you specify DENY, not only will attempts to load the page in a frame fail when loaded from other sites, attempts to do so will fail when loaded from the same site. On the other hand, if you specify SAMEORIGIN, you can still use the page in a frame as long as the site including it in a frame it is the same as the one serving the page. + +[[nsa-frame-options-strategy]] +* **strategy** +Select the `AllowFromStrategy` to use when using the ALLOW-FROM policy. + +** `static` Use a single static ALLOW-FROM value. The value can be set through the <> attribute. +** `regexp` Use a regelur expression to validate incoming requests and if they are allowed. The regular expression can be set through the <> attribute. The request parameter used to retrieve the value to validate can be specified using the <>. +** `whitelist` A comma-seperated list containing the allowed domains. The comma-seperated list can be set through the <> attribute. The request parameter used to retrieve the value to validate can be specified using the <>. + + + + +[[nsa-frame-options-ref]] +* **ref** +Instead of using one of the predefined strategies it is also possible to use a custom `AllowFromStrategy`. The reference to this bean can be specified through this ref attribute. + + +[[nsa-frame-options-value]] +* **value** +The value to use when ALLOW-FROM is used a <>. + + +[[nsa-frame-options-from-parameter]] +* **from-parameter** +Specify the name of the request parameter to use when using regexp or whitelist for the ALLOW-FROM strategy. + + +[[nsa-frame-options-parents]] +====== Parent Elements of + +* <> + + + +[[nsa-xss-protection]] +===== +Adds the http://blogs.msdn.com/b/ie/archive/2008/07/02/ie8-security-part-iv-the-xss-filter.aspx[X-XSS-Protection header] to the response to assist in protecting against http://en.wikipedia.org/wiki/Cross-site_scripting#Non-Persistent[reflected / “Type-1” Cross-Site Scripting (XSS)] attacks. This is in no-way a full protection to XSS attacks! + + +[[nsa-xss-protection-attributes]] +====== Attributes + + +[[nsa-xss-protection-enabled]] +* **xss-protection-enabled** +Enable or Disable http://en.wikipedia.org/wiki/Cross-site_scripting#Non-Persistent[reflected / “Type-1” Cross-Site Scripting (XSS)] protection. + + +[[nsa-xss-protection-block]] +* **xss-protection-block** +When true and xss-protection-enabled is true, adds mode=block to the header. This indicates to the browser that the page should not be loaded at all. When false and xss-protection-enabled is true, the page will still be rendered when an reflected attack is detected but the response will be modified to protect against the attack. Note that there are sometimes ways of bypassing this mode which can often times make blocking the page more desirable. + + +[[nsa-xss-protection-parents]] +====== Parent Elements of + +* <> + + + +[[nsa-content-type-options]] +===== +Add the X-Content-Type-Options header with the value of nosniff to the response. This http://blogs.msdn.com/b/ie/archive/2008/09/02/ie8-security-part-vi-beta-2-update.aspx[disables MIME-sniffing] for IE8+ and Chrome extensions. + + +[[nsa-content-type-options-parents]] +====== Parent Elements of + + +* <> + + + +[[nsa-header]] +=====
+Add additional headers to the response, both the name and value need to be specified. + + +[[nsa-header-attributes]] +====== Attributes + + +[[nsa-header-name]] +* **header-name** +The `name` of the header. + + +[[nsa-header-value]] +* **header-value** +The `value` of the header to add. + + +[[nsa-header-ref]] +* **header-ref** +Reference to a custom implementation of the `HeaderWriter` interface. + + +[[nsa-header-parents]] +====== Parent Elements of
+ + +* <> + + + +[[nsa-anonymous]] +===== +Adds an `AnonymousAuthenticationFilter` to the stack and an `AnonymousAuthenticationProvider`. Required if you are using the `IS_AUTHENTICATED_ANONYMOUSLY` attribute. + + +[[nsa-anonymous-parents]] +====== Parent Elements of + + +* <> + + + +[[nsa-anonymous-attributes]] +====== Attributes + + +[[nsa-anonymous-enabled]] +* **enabled** +With the default namespace setup, the anonymous "authentication" facility is automatically enabled. You can disable it using this property. + + +[[nsa-anonymous-granted-authority]] +* **granted-authority** +The granted authority that should be assigned to the anonymous request. Commonly this is used to assign the anonymous request particular roles, which can subsequently be used in authorization decisions. If unset, defaults to `ROLE_ANONYMOUS`. + + +[[nsa-anonymous-key]] +* **key** +The key shared between the provider and filter. This generally does not need to be set. If unset, it will default to a secure randomly generated value. This means setting this value can improve startup time when using the anonymous functionality since secure random values can take a while to be generated. + + +[[nsa-anonymous-username]] +* **username** +The username that should be assigned to the anonymous request. This allows the principal to be identified, which may be important for logging and auditing. if unset, defaults to `anonymousUser`. + + +[[nsa-csrf]] +===== +This element will add http://en.wikipedia.org/wiki/Cross-site_request_forgery[Cross Site Request Forger (CSRF)] protection to the application. It also updates the default RequestCache to only replay "GET" requests upon successful authentication. Additional information can be found in the <> section of the reference. + + +[[nsa-csrf-parents]] +====== Parent Elements of + + +* <> + + + +[[nsa-csrf-attributes]] +====== Attributes + + +[[nsa-csrf-token-repository-ref]] +* **token-repository-ref** +The CsrfTokenRepository to use. The default is `HttpSessionCsrfTokenRepository`. + + +[[nsa-csrf-request-matcher-ref]] +* **request-matcher-ref** +The RequestMatcher instance to be used to determine if CSRF should be applied. Default is any HTTP method except "GET", "TRACE", "HEAD", "OPTIONS". + + +[[nsa-custom-filter]] +===== +This element is used to add a filter to the filter chain. It doesn't create any additional beans but is used to select a bean of type `javax.servlet.Filter` which is already defined in the application context and add that at a particular position in the filter chain maintained by Spring Security. Full details can be found in the <>. + + +[[nsa-custom-filter-parents]] +====== Parent Elements of + + +* <> + + + +[[nsa-custom-filter-attributes]] +====== Attributes + + +[[nsa-custom-filter-after]] +* **after** +The filter immediately after which the custom-filter should be placed in the chain. This feature will only be needed by advanced users who wish to mix their own filters into the security filter chain and have some knowledge of the standard Spring Security filters. The filter names map to specific Spring Security implementation filters. + + +[[nsa-custom-filter-before]] +* **before** +The filter immediately before which the custom-filter should be placed in the chain + + +[[nsa-custom-filter-position]] +* **position** +The explicit position at which the custom-filter should be placed in the chain. Use if you are replacing a standard filter. + + +[[nsa-custom-filter-ref]] +* **ref** +Defines a reference to a Spring bean that implements `Filter`. + + +[[nsa-expression-handler]] +===== +Defines the `SecurityExpressionHandler` instance which will be used if expression-based access-control is enabled. A default implementation (with no ACL support) will be used if not supplied. + + +[[nsa-expression-handler-parents]] +====== Parent Elements of + + +* <> +* <> + + + +[[nsa-expression-handler-attributes]] +====== Attributes + + +[[nsa-expression-handler-ref]] +* **ref** +Defines a reference to a Spring bean that implements `SecurityExpressionHandler`. + + +[[nsa-form-login]] +===== +Used to add an `UsernamePasswordAuthenticationFilter` to the filter stack and an `LoginUrlAuthenticationEntryPoint` to the application context to provide authentication on demand. This will always take precedence over other namespace-created entry points. If no attributes are supplied, a login page will be generated automatically at the URL "/spring_security_login" footnote:[ +This feature is really just provided for convenience and is not intended for production (where a view technology will have been chosen and can be used to render a customized login page). The class `DefaultLoginPageGeneratingFilter` is responsible for rendering the login page and will provide login forms for both normal form login and/or OpenID if required. +] The behaviour can be customized using the <` Attributes>>. + + +[[nsa-form-login-parents]] +====== Parent Elements of + + +* <> + + + +[[nsa-form-login-attributes]] +====== Attributes + + +[[nsa-form-login-always-use-default-target]] +* **always-use-default-target** +If set to `true`, the user will always start at the value given by <>, regardless of how they arrived at the login page. Maps to the `alwaysUseDefaultTargetUrl` property of `UsernamePasswordAuthenticationFilter`. Default value is `false`. + + +[[nsa-form-login-authentication-details-source-ref]] +* **authentication-details-source-ref** +Reference to an `AuthenticationDetailsSource` which will be used by the authentication filter + + +[[nsa-form-login-authentication-failure-handler-ref]] +* **authentication-failure-handler-ref** +Can be used as an alternative to <>, giving you full control over the navigation flow after an authentication failure. The value should be he name of an `AuthenticationFailureHandler` bean in the application context. + + +[[nsa-form-login-authentication-failure-url]] +* **authentication-failure-url** +Maps to the `authenticationFailureUrl` property of `UsernamePasswordAuthenticationFilter`. Defines the URL the browser will be redirected to on login failure. Defaults to `/spring_security_login?login_error`, which will be automatically handled by the automatic login page generator, re-rendering the login page with an error message. + + +[[nsa-form-login-authentication-success-handler-ref]] +* **authentication-success-handler-ref** +This can be used as an alternative to <> and <>, giving you full control over the navigation flow after a successful authentication. The value should be the name of an `AuthenticationSuccessHandler` bean in the application context. By default, an implementation of `SavedRequestAwareAuthenticationSuccessHandler` is used and injected with the <>. + + +[[nsa-form-login-default-target-url]] +* **default-target-url** +Maps to the `defaultTargetUrl` property of `UsernamePasswordAuthenticationFilter`. If not set, the default value is "/" (the application root). A user will be taken to this URL after logging in, provided they were not asked to login while attempting to access a secured resource, when they will be taken to the originally requested URL. + + +[[nsa-form-login-login-page]] +* **login-page** +The URL that should be used to render the login page. Maps to the `loginFormUrl` property of the `LoginUrlAuthenticationEntryPoint`. Defaults to "/spring_security_login". + + +[[nsa-form-login-login-processing-url]] +* **login-processing-url** +Maps to the `filterProcessesUrl` property of `UsernamePasswordAuthenticationFilter`. The default value is "/j_spring_security_check". + + +[[nsa-form-login-password-parameter]] +* **password-parameter** +The name of the request parameter which contains the password. Defaults to "j_password". + + +[[nsa-form-login-username-parameter]] +* **username-parameter** +The name of the request parameter which contains the username. Defaults to "j_username". + + +[[nsa-http-basic]] +===== +Adds a `BasicAuthenticationFilter` and `BasicAuthenticationEntryPoint` to the configuration. The latter will only be used as the configuration entry point if form-based login is not enabled. + + +[[nsa-http-basic-parents]] +====== Parent Elements of + + +* <> + + + +[[nsa-http-basic-attributes]] +====== Attributes + + +[[nsa-http-basic-authentication-details-source-ref]] +* **authentication-details-source-ref** +Reference to an `AuthenticationDetailsSource` which will be used by the authentication filter + + +[[nsa-http-basic-entry-point-ref]] +* **entry-point-ref** +Sets the `AuthenticationEntryPoint` which is used by the `BasicAuthenticationFilter`. + + +[[nsa-http-firewall]] +===== Element +This is a top-level element which can be used to inject a custom implementation of `HttpFirewall` into the `FilterChainProxy` created by the namespace. The default implementation should be suitable for most applications. + + +[[nsa-http-firewall-attributes]] +====== Attributes + + +[[nsa-http-firewall-ref]] +* **ref** +Defines a reference to a Spring bean that implements `HttpFirewall`. + + +[[nsa-intercept-url]] +===== +This element is used to define the set of URL patterns that the application is interested in and to configure how they should be handled. It is used to construct the `FilterInvocationSecurityMetadataSource` used by the `FilterSecurityInterceptor`. It is also responsible for configuring a `ChannelProcessingFilter` if particular URLs need to be accessed by HTTPS, for example. When matching the specified patterns against an incoming request, the matching is done in the order in which the elements are declared. So the most specific matches patterns should come first and the most general should come last. + + +[[nsa-intercept-url-parents]] +====== Parent Elements of + + +* <> +* <> +* <> + + + +[[nsa-intercept-url-attributes]] +====== Attributes + + +[[nsa-intercept-url-access]] +* **access** +Lists the access attributes which will be stored in the `FilterInvocationSecurityMetadataSource` for the defined URL pattern/method combination. This should be a comma-separated list of the security configuration attributes (such as role names). + + +[[nsa-intercept-url-filters]] +* **filters** +Can only take the value "none". This will cause any matching request to bypass the Spring Security filter chain entirely. None of the rest of the `` configuration will have any effect on the request and there will be no security context available for its duration. Access to secured methods during the request will fail. + + +[[nsa-intercept-url-method]] +* **method** +The HTTP Method which will be used in combination with the pattern to match an incoming request. If omitted, any method will match. If an identical pattern is specified with and without a method, the method-specific match will take precedence. + + +[[nsa-intercept-url-pattern]] +* **pattern** +The pattern which defines the URL path. The content will depend on the `request-matcher` attribute from the containing http element, so will default to ant path syntax. + + +[[nsa-intercept-url-requires-channel]] +* **requires-channel** +Can be "http" or "https" depending on whether a particular URL pattern should be accessed over HTTP or HTTPS respectively. Alternatively the value "any" can be used when there is no preference. If this attribute is present on any `` element, then a `ChannelProcessingFilter` will be added to the filter stack and its additional dependencies added to the application context. + +If a `` configuration is added, this will be used to by the `SecureChannelProcessor` and `InsecureChannelProcessor` beans to determine the ports used for redirecting to HTTP/HTTPS. + + +[[nsa-jee]] +===== +Adds a J2eePreAuthenticatedProcessingFilter to the filter chain to provide integration with container authentication. + + +[[nsa-jee-parents]] +====== Parent Elements of + + +* <> + + + +[[nsa-jee-attributes]] +====== Attributes + + +[[nsa-jee-mappable-roles]] +* **mappable-roles** +A comma-separate list of roles to look for in the incoming HttpServletRequest. + + +[[nsa-jee-user-service-ref]] +* **user-service-ref** +A reference to a user-service (or UserDetailsService bean) Id + + +[[nsa-logout]] +===== +Adds a `LogoutFilter` to the filter stack. This is configured with a `SecurityContextLogoutHandler`. + + +[[nsa-logout-parents]] +====== Parent Elements of + + +* <> + + + +[[nsa-logout-attributes]] +====== Attributes + + +[[nsa-logout-delete-cookies]] +* **delete-cookies** +A comma-separated list of the names of cookies which should be deleted when the user logs out. + + +[[nsa-logout-invalidate-session]] +* **invalidate-session** +Maps to the `invalidateHttpSession` of the `SecurityContextLogoutHandler`. Defaults to "true", so the session will be invalidated on logout. + + +[[nsa-logout-logout-success-url]] +* **logout-success-url** +The destination URL which the user will be taken to after logging out. Defaults to "/". + ++ + +Setting this attribute will inject the `SessionManagementFilter` with a `SimpleRedirectInvalidSessionStrategy` configured with the attribute value. When an invalid session ID is submitted, the strategy will be invoked, redirecting to the configured URL. + + +[[nsa-logout-logout-url]] +* **logout-url** +The URL which will cause a logout (i.e. which will be processed by the filter). Defaults to "/j_spring_security_logout". + + +[[nsa-logout-success-handler-ref]] +* **success-handler-ref** +May be used to supply an instance of `LogoutSuccessHandler` which will be invoked to control the navigation after logging out. + + +[[nsa-openid-login]] +===== +Similar to `` and has the same attributes. The default value for `login-processing-url` is "/j_spring_openid_security_check". An `OpenIDAuthenticationFilter` and `OpenIDAuthenticationProvider` will be registered. The latter requires a reference to a `UserDetailsService`. Again, this can be specified by `id`, using the `user-service-ref` attribute, or will be located automatically in the application context. + + +[[nsa-openid-login-parents]] +====== Parent Elements of + + +* <> + + + +[[nsa-openid-login-attributes]] +====== Attributes + + +[[nsa-openid-login-always-use-default-target]] +* **always-use-default-target** +Whether the user should always be redirected to the default-target-url after login. + + +[[nsa-openid-login-authentication-details-source-ref]] +* **authentication-details-source-ref** +Reference to an AuthenticationDetailsSource which will be used by the authentication filter + + +[[nsa-openid-login-authentication-failure-handler-ref]] +* **authentication-failure-handler-ref** +Reference to an AuthenticationFailureHandler bean which should be used to handle a failed authentication request. Should not be used in combination with authentication-failure-url as the implementation should always deal with navigation to the subsequent destination + + +[[nsa-openid-login-authentication-failure-url]] +* **authentication-failure-url** +The URL for the login failure page. If no login failure URL is specified, Spring Security will automatically create a failure login URL at /spring_security_login?login_error and a corresponding filter to render that login failure URL when requested. + + +[[nsa-openid-login-authentication-success-handler-ref]] +* **authentication-success-handler-ref** +Reference to an AuthenticationSuccessHandler bean which should be used to handle a successful authentication request. Should not be used in combination with <> (or <>) as the implementation should always deal with navigation to the subsequent destination + + +[[nsa-openid-login-default-target-url]] +* **default-target-url** +The URL that will be redirected to after successful authentication, if the user's previous action could not be resumed. This generally happens if the user visits a login page without having first requested a secured operation that triggers authentication. If unspecified, defaults to the root of the application. + + +[[nsa-openid-login-login-page]] +* **login-page** +The URL for the login page. If no login URL is specified, Spring Security will automatically create a login URL at /spring_security_login and a corresponding filter to render that login URL when requested. + + +[[nsa-openid-login-login-processing-url]] +* **login-processing-url** +The URL that the login form is posted to. If unspecified, it defaults to /j_spring_security_check. + + +[[nsa-openid-login-password-parameter]] +* **password-parameter** +The name of the request parameter which contains the password. Defaults to "j_password". + + +[[nsa-openid-login-user-service-ref]] +* **user-service-ref** +A reference to a user-service (or UserDetailsService bean) Id + + +[[nsa-openid-login-username-parameter]] +* **username-parameter** +The name of the request parameter which contains the username. Defaults to "j_username". + + +[[nsa-openid-login-children]] +====== Child Elements of +* <> + + + +[[nsa-attribute-exchange]] +===== +The `attribute-exchange` element defines the list of attributes which should be requested from the identity provider. An example can be found in the <> section of the namespace configuration chapter. More than one can be used, in which case each must have an `identifier-match` attribute, containing a regular expression which is matched against the supplied OpenID identifier. This allows different attribute lists to be fetched from different providers (Google, Yahoo etc). + + +[[nsa-attribute-exchange-parents]] +====== Parent Elements of + + +* <> + + + +[[nsa-attribute-exchange-attributes]] +====== Attributes + + +[[nsa-attribute-exchange-identifier-match]] +* **identifier-match** +A regular expression which will be compared against the claimed identity, when deciding which attribute-exchange configuration to use during authentication. + + +[[nsa-attribute-exchange-children]] +====== Child Elements of + + +* <> + + + +[[nsa-openid-attribute]] +===== +Attributes used when making an OpenID AX http://openid.net/specs/openid-attribute-exchange-1_0.html#fetch_request[ Fetch Request] + + +[[nsa-openid-attribute-parents]] +====== Parent Elements of + + +* <> + + + +[[nsa-openid-attribute-attributes]] +====== Attributes + + +[[nsa-openid-attribute-count]] +* **count** +Specifies the number of attributes that you wish to get back. For example, return 3 emails. The default value is 1. + + +[[nsa-openid-attribute-name]] +* **name** +Specifies the name of the attribute that you wish to get back. For example, email. + + +[[nsa-openid-attribute-required]] +* **required** +Specifies if this attribute is required to the OP, but does not error out if the OP does not return the attribute. Default is false. + + +[[nsa-openid-attribute-type]] +* **type** +Specifies the attribute type. For example, http://axschema.org/contact/email. See your OP's documentation for valid attribute types. + + +[[nsa-port-mappings]] +===== +By default, an instance of `PortMapperImpl` will be added to the configuration for use in redirecting to secure and insecure URLs. This element can optionally be used to override the default mappings which that class defines. Each child `` element defines a pair of HTTP:HTTPS ports. The default mappings are 80:443 and 8080:8443. An example of overriding these can be found in the <>. + + +[[nsa-port-mappings-parents]] +====== Parent Elements of + + +* <> + + + +[[nsa-port-mappings-children]] +====== Child Elements of + + +* <> + + + +[[nsa-port-mapping]] +===== +Provides a method to map http ports to https ports when forcing a redirect. + + +[[nsa-port-mapping-parents]] +====== Parent Elements of + + +* <> + + + +[[nsa-port-mapping-attributes]] +====== Attributes + + +[[nsa-port-mapping-http]] +* **http** +The http port to use. + + +[[nsa-port-mapping-https]] +* **https** +The https port to use. + + +[[nsa-remember-me]] +===== +Adds the `RememberMeAuthenticationFilter` to the stack. This in turn will be configured with either a `TokenBasedRememberMeServices`, a `PersistentTokenBasedRememberMeServices` or a user-specified bean implementing `RememberMeServices` depending on the attribute settings. + + +[[nsa-remember-me-parents]] +====== Parent Elements of + + +* <> + + + +[[nsa-remember-me-attributes]] +====== Attributes + + +[[nsa-remember-me-authentication-success-handler-ref]] +* **authentication-success-handler-ref** +Sets the `authenticationSuccessHandler` property on the `RememberMeAuthenticationFilter` if custom navigation is required. The value should be the name of a `AuthenticationSuccessHandler` bean in the application context. + + +[[nsa-remember-me-data-source-ref]] +* **data-source-ref** +A reference to a `DataSource` bean. If this is set, `PersistentTokenBasedRememberMeServices` will be used and configured with a `JdbcTokenRepositoryImpl` instance. + + +[[nsa-remember-me-remember-me-parameter]] +* **remember-me-parameter** +The name of the request parameter which toggles remember-me authentication. Defaults to "_spring_security_remember_me". Maps to the "parameter" property of `AbstractRememberMeServices`. + + +[[nsa-remember-me-key]] +* **key** +Maps to the "key" property of `AbstractRememberMeServices`. Should be set to a unique value to ensure that remember-me cookies are only valid within the one application footnote:[ +This doesn't affect the use of `PersistentTokenBasedRememberMeServices`, where the tokens are stored on the server side. +]. If this is not set a secure random value will be generated. Since generating secure random values can take a while, setting this value explicitly can help improve startup times when using the remember me functionality. + + +[[nsa-remember-me-services-alias]] +* **services-alias** +Exports the internally defined `RememberMeServices` as a bean alias, allowing it to be used by other beans in the application context. + + +[[nsa-remember-me-services-ref]] +* **services-ref** +Allows complete control of the `RememberMeServices` implementation that will be used by the filter. The value should be the `id` of a bean in the application context which implements this interface. Should also implement `LogoutHandler` if a logout filter is in use. + + +[[nsa-remember-me-token-repository-ref]] +* **token-repository-ref** +Configures a `PersistentTokenBasedRememberMeServices` but allows the use of a custom `PersistentTokenRepository` bean. + + +[[nsa-remember-me-token-validity-seconds]] +* **token-validity-seconds** +Maps to the `tokenValiditySeconds` property of `AbstractRememberMeServices`. Specifies the period in seconds for which the remember-me cookie should be valid. By default it will be valid for 14 days. + + +[[nsa-remember-me-use-secure-cookie]] +* **use-secure-cookie** +It is recommended that remember-me cookies are only submitted over HTTPS and thus should be flagged as "secure". By default, a secure cookie will be used if the connection over which the login request is made is secure (as it should be). If you set this property to `false`, secure cookies will not be used. Setting it to `true` will always set the secure flag on the cookie. This attribute maps to the `useSecureCookie` property of `AbstractRememberMeServices`. + + +[[nsa-remember-me-user-service-ref]] +* **user-service-ref** +The remember-me services implementations require access to a `UserDetailsService`, so there has to be one defined in the application context. If there is only one, it will be selected and used automatically by the namespace configuration. If there are multiple instances, you can specify a bean `id` explicitly using this attribute. + + +[[nsa-request-cache]] +===== Element +Sets the `RequestCache` instance which will be used by the `ExceptionTranslationFilter` to store request information before invoking an `AuthenticationEntryPoint`. + + +[[nsa-request-cache-parents]] +====== Parent Elements of + +* <> + +[[nsa-request-cache-attributes]] +====== Attributes + + +[[nsa-request-cache-ref]] +* **ref** +Defines a reference to a Spring bean that is a `RequestCache`. + + +[[nsa-session-management]] +===== +Session-management related functionality is implemented by the addition of a `SessionManagementFilter` to the filter stack. + + +[[nsa-session-management-parents]] +====== Parent Elements of + + +* <> + + + +[[nsa-session-management-attributes]] +====== Attributes + + +[[nsa-session-management-invalid-session-url]] +* **invalid-session-url** +Setting this attribute will inject the `SessionManagementFilter` with a `SimpleRedirectInvalidSessionStrategy` configured with the attribute value. When an invalid session ID is submitted, the strategy will be invoked, redirecting to the configured URL. + + +[[nsa-session-management-session-authentication-error-url]] +* **session-authentication-error-url** +Defines the URL of the error page which should be shown when the SessionAuthenticationStrategy raises an exception. If not set, an unauthorized (401) error code will be returned to the client. Note that this attribute doesn't apply if the error occurs during a form-based login, where the URL for authentication failure will take precedence. + + +[[nsa-session-management-session-authentication-strategy-ref]] +* **session-authentication-strategy-ref** +Allows injection of the SessionAuthenticationStrategy instance used by the SessionManagementFilter + + +[[nsa-session-management-session-fixation-protection]] +* **session-fixation-protection** +Indicates how session fixation protection will be applied when a user authenticates. If set to "none", no protection will be applied. "newSession" will create a new empty session, with only Spring Security-related attributes migrated. "migrateSession" will create a new session and copy all session attributes to the new session. In Servlet 3.1 (Java EE 7) and newer containers, specifying "changeSessionId" will keep the existing session and use the container-supplied session fixation protection (HttpServletRequest#changeSessionId()). Defaults to "changeSessionId" in Servlet 3.1 and newer containers, "migrateSession" in older containers. Throws an exception if "changeSessionId" is used in older containers. + ++ + +If session fixation protection is enabled, the `SessionManagementFilter` is injected with an appropriately configured `DefaultSessionAuthenticationStrategy`. See the Javadoc for this class for more details. + + +[[nsa-session-management-children]] +====== Child Elements of + + +* <> + + + +[[nsa-concurrency-control]] +===== +Adds support for concurrent session control, allowing limits to be placed on the number of active sessions a user can have. A `ConcurrentSessionFilter` will be created, and a `ConcurrentSessionControlAuthenticationStrategy` will be used with the `SessionManagementFilter`. If a `form-login` element has been declared, the strategy object will also be injected into the created authentication filter. An instance of `SessionRegistry` (a `SessionRegistryImpl` instance unless the user wishes to use a custom bean) will be created for use by the strategy. + + +[[nsa-concurrency-control-parents]] +====== Parent Elements of + + +* <> + + + +[[nsa-concurrency-control-attributes]] +====== Attributes + + +[[nsa-concurrency-control-error-if-maximum-exceeded]] +* **error-if-maximum-exceeded** +If set to "true" a `SessionAuthenticationException` will be raised when a user attempts to exceed the maximum allowed number of sessions. The default behaviour is to expire the original session. + + +[[nsa-concurrency-control-expired-url]] +* **expired-url** +The URL a user will be redirected to if they attempt to use a session which has been "expired" by the concurrent session controller because the user has exceeded the number of allowed sessions and has logged in again elsewhere. Should be set unless `exception-if-maximum-exceeded` is set. If no value is supplied, an expiry message will just be written directly back to the response. + + +[[nsa-concurrency-control-max-sessions]] +* **max-sessions** +Maps to the `maximumSessions` property of `ConcurrentSessionControlAuthenticationStrategy`. + + +[[nsa-concurrency-control-session-registry-alias]] +* **session-registry-alias** +It can also be useful to have a reference to the internal session registry for use in your own beans or an admin interface. You can expose the internal bean using the `session-registry-alias` attribute, giving it a name that you can use elsewhere in your configuration. + + +[[nsa-concurrency-control-session-registry-ref]] +* **session-registry-ref** +The user can supply their own `SessionRegistry` implementation using the `session-registry-ref` attribute. The other concurrent session control beans will be wired up to use it. + + +[[nsa-x509]] +===== +Adds support for X.509 authentication. An `X509AuthenticationFilter` will be added to the stack and an `Http403ForbiddenEntryPoint` bean will be created. The latter will only be used if no other authentication mechanisms are in use (its only functionality is to return an HTTP 403 error code). A `PreAuthenticatedAuthenticationProvider` will also be created which delegates the loading of user authorities to a `UserDetailsService`. + + +[[nsa-x509-parents]] +====== Parent Elements of + + +* <> + + + +[[nsa-x509-attributes]] +====== Attributes + + +[[nsa-x509-authentication-details-source-ref]] +* **authentication-details-source-ref** +A reference to an `AuthenticationDetailsSource` + + +[[nsa-x509-subject-principal-regex]] +* **subject-principal-regex** +Defines a regular expression which will be used to extract the username from the certificate (for use with the `UserDetailsService`). + + +[[nsa-x509-user-service-ref]] +* **user-service-ref** +Allows a specific `UserDetailsService` to be used with X.509 in the case where multiple instances are configured. If not set, an attempt will be made to locate a suitable instance automatically and use that. + + +[[nsa-filter-chain-map]] +===== +Used to explicitly configure a FilterChainProxy instance with a FilterChainMap + + +[[nsa-filter-chain-map-attributes]] +====== Attributes + + +[[nsa-filter-chain-map-path-type]] +* **path-type** +Superseded by the <> attribute + + +[[nsa-filter-chain-map-request-matcher]] +* **request-matcher** +Supersedes the 'path-type' attribute. Defines the strategy use for matching incoming requests. Currently the options are 'ant' (for ant path patterns), 'regex' for regular expressions and 'ciRegex' for case-insensitive regular expressions. + + +[[nsa-filter-chain-map-children]] +====== Child Elements of + + +* <> + + + +[[nsa-filter-chain]] +===== +Used within to define a specific URL pattern and the list of filters which apply to the URLs matching that pattern. When multiple filter-chain elements are assembled in a list in order to configure a FilterChainProxy, the most specific patterns must be placed at the top of the list, with most general ones at the bottom. + + +[[nsa-filter-chain-parents]] +====== Parent Elements of + + +* <> + + + +[[nsa-filter-chain-attributes]] +====== Attributes + + +[[nsa-filter-chain-filters]] +* **filters** +A comma separated list of references to Spring beans that implement `Filter`. The value "none" means that no `Filter`'s should be used for this `FilterChain`. + + +[[nsa-filter-chain-pattern]] +* **pattern** +A-pattern that creates RequestMatcher in combination with the <> + + +[[nsa-filter-chain-request-matcher-ref]] +* **request-matcher-ref** +A reference to a `RequestMatcher` that will be used to determine if the `Filter`'s from the `filters` attribute should be invoked. + + +[[nsa-filter-invocation-definition-source]] +===== +Deprecated synonym for filter-security-metadata-source + + +[[nsa-filter-invocation-definition-source-attributes]] +====== Attributes + + +[[nsa-filter-invocation-definition-source-id]] +* **id** +A bean identifier, used for referring to the bean elsewhere in the context. + + +[[nsa-filter-invocation-definition-source-lowercase-comparisons]] +* **lowercase-comparisons** +Compare after forcing to lowercase + + +[[nsa-filter-invocation-definition-source-path-type]] +* **path-type** +Superseded by <> + + +[[nsa-filter-invocation-definition-source-request-matcher]] +* **request-matcher** +Supersedes the 'path-type' attribute. Defines the strategy use for matching incoming requests. Currently the options are 'ant' (for ant path patterns), 'regex' for regular expressions and 'ciRegex' for case-insensitive regular expressions. + + +[[nsa-filter-invocation-definition-source-use-expressions]] +* **use-expressions** +Enables the use of expressions in the 'access' attributes in elements rather than the traditional list of configuration attributes. Defaults to 'false'. If enabled, each attribute should contain a single boolean expression. If the expression evaluates to 'true', access will be granted. + + +[[nsa-filter-invocation-definition-source-children]] +====== Child Elements of + + +* <> + + + +[[nsa-filter-security-metadata-source]] +===== +Used to explicitly configure a FilterSecurityMetadataSource bean for use with a FilterSecurityInterceptor. Usually only needed if you are configuring a FilterChainProxy explicitly, rather than using the element. The intercept-url elements used should only contain pattern, method and access attributes. Any others will result in a configuration error. + + +[[nsa-filter-security-metadata-source-attributes]] +====== Attributes + + +[[nsa-filter-security-metadata-source-id]] +* **id** +A bean identifier, used for referring to the bean elsewhere in the context. + + +[[nsa-filter-security-metadata-source-lowercase-comparisons]] +* **lowercase-comparisons** +Compare after forcing to lower case + + +[[nsa-filter-security-metadata-source-path-type]] +* **path-type** +Superseded by <> + + +[[nsa-filter-security-metadata-source-request-matcher]] +* **request-matcher** +Supersedes the 'path-type' attribute. Defines the strategy use for matching incoming requests. Currently the options are 'ant' (for ant path patterns), 'regex' for regular expressions and 'ciRegex' for case-insensitive regular expressions. + + +[[nsa-filter-security-metadata-source-use-expressions]] +* **use-expressions** +Enables the use of expressions in the 'access' attributes in elements rather than the traditional list of configuration attributes. Defaults to 'false'. If enabled, each attribute should contain a single boolean expression. If the expression evaluates to 'true', access will be granted. + + +[[nsa-filter-security-metadata-source-children]] +====== Child Elements of + + +* <> + + + +[[nsa-authentication]] +==== Authentication Services +Before Spring Security 3.0, an `AuthenticationManager` was automatically registered internally. Now you must register one explicitly using the `` element. This creates an instance of Spring Security's `ProviderManager` class, which needs to be configured with a list of one or more `AuthenticationProvider` instances. These can either be created using syntax elements provided by the namespace, or they can be standard bean definitions, marked for addition to the list using the `authentication-provider` element. + + +[[nsa-authentication-manager]] +===== +Every Spring Security application which uses the namespace must have include this element somewhere. It is responsible for registering the `AuthenticationManager` which provides authentication services to the application. All elements which create `AuthenticationProvider` instances should be children of this element. + + +[[nsa-authentication-manager-attributes]] +====== Attributes + + +[[nsa-authentication-manager-alias]] +* **alias** +This attribute allows you to define an alias name for the internal instance for use in your own configuration. Its use is described in the<>. + + +[[nsa-authentication-manager-erase-credentials]] +* **erase-credentials** +If set to true, the AuthenticationManger will attempt to clear any credentials data in the returned Authentication object, once the user has been authenticated. Literally it maps to the `eraseCredentialsAfterAuthentication` property of the `ProviderManager`. This is discussed in the <> chapter. + + +[[nsa-authentication-manager-id]] +* **id** +This attribute allows you to define an id for the internal instance for use in your own configuration. It is the same a the alias element, but provides a more consistent experience with elements that use the id attribute. + + +[[nsa-authentication-manager-children]] +====== Child Elements of + + +* <> +* <> + + + +[[nsa-authentication-provider]] +===== +Unless used with a `ref` attribute, this element is shorthand for configuring a <>. `DaoAuthenticationProvider` loads user information from a `UserDetailsService` and compares the username/password combination with the values supplied at login. The `UserDetailsService` instance can be defined either by using an available namespace element ( `jdbc-user-service` or by using the `user-service-ref` attribute to point to a bean defined elsewhere in the application context). You can find examples of these variations in the <>. + + +[[nsa-authentication-provider-parents]] +====== Parent Elements of + + +* <> + + + +[[nsa-authentication-provider-attributes]] +====== Attributes + + +[[nsa-authentication-provider-ref]] +* **ref** +Defines a reference to a Spring bean that implements `AuthenticationProvider `. + +If you have written your own `AuthenticationProvider` implementation (or want to configure one of Spring Security's own implementations as a traditional bean for some reason, then you can use the following syntax to add it to the internal `ProviderManager`'s list: + +[source,xml] +---- + + + + + + +---- + + + + +[[nsa-authentication-provider-user-service-ref]] +* **user-service-ref** +A reference to a bean that implements UserDetailsService that may be created using the standard bean element or the custom user-service element. + + +[[nsa-authentication-provider-children]] +====== Child Elements of + + +* <> +* <> +* <> +* <> + + + +[[nsa-jdbc-user-service]] +===== +Causes creation of a JDBC-based UserDetailsService. + + +[[nsa-jdbc-user-service-attributes]] +====== Attributes + + +[[nsa-jdbc-user-service-authorities-by-username-query]] +* **authorities-by-username-query** +An SQL statement to query for a user's granted authorities given a username. + +The default is + +[source] +---- +select username, authority from authorities where username = ? +---- + + + + +[[nsa-jdbc-user-service-cache-ref]] +* **cache-ref** +Defines a reference to a cache for use with a UserDetailsService. + + +[[nsa-jdbc-user-service-data-source-ref]] +* **data-source-ref** +The bean ID of the DataSource which provides the required tables. + + +[[nsa-jdbc-user-service-group-authorities-by-username-query]] +* **group-authorities-by-username-query** +An SQL statement to query user's group authorities given a username. The default is + ++ + +[source] +---- +select + g.id, g.group_name, ga.authority +from + groups g, group_members gm, group_authorities ga +where + gm.username = ? and g.id = ga.group_id and g.id = gm.group_id +---- + + + + +[[nsa-jdbc-user-service-id]] +* **id** +A bean identifier, used for referring to the bean elsewhere in the context. + + +[[nsa-jdbc-user-service-role-prefix]] +* **role-prefix** +A non-empty string prefix that will be added to role strings loaded from persistent storage (default is "ROLE_"). Use the value "none" for no prefix in cases where the default is non-empty. + + +[[nsa-jdbc-user-service-users-by-username-query]] +* **users-by-username-query** +An SQL statement to query a username, password, and enabled status given a username. The default is + ++ + +[source] +---- +select username, password, enabled from users where username = ? +---- + + + + +[[nsa-password-encoder]] +===== +Authentication providers can optionally be configured to use a password encoder as described in the <>. This will result in the bean being injected with the appropriate `PasswordEncoder` instance, potentially with an accompanying `SaltSource` bean to provide salt values for hashing. + + +[[nsa-password-encoder-parents]] +====== Parent Elements of + + +* <> +* <> + + + +[[nsa-password-encoder-attributes]] +====== Attributes + + +[[nsa-password-encoder-base64]] +* **base64** +Whether a string should be base64 encoded + + +[[nsa-password-encoder-hash]] +* **hash** +Defines the hashing algorithm used on user passwords. We recommend strongly against using MD4, as it is a very weak hashing algorithm. + + +[[nsa-password-encoder-ref]] +* **ref** +Defines a reference to a Spring bean that implements `PasswordEncoder `. + + +[[nsa-password-encoder-children]] +====== Child Elements of + + +* <> + + + +[[nsa-salt-source]] +===== +Password salting strategy. A system-wide constant or a property from the UserDetails object can be used. + + +[[nsa-salt-source-parents]] +====== Parent Elements of + + +* <> + + + +[[nsa-salt-source-attributes]] +====== Attributes + + +[[nsa-salt-source-ref]] +* **ref** +Defines a reference to a Spring bean Id. + + +[[nsa-salt-source-system-wide]] +* **system-wide** +A single value that will be used as the salt for a password encoder. + + +[[nsa-salt-source-user-property]] +* **user-property** +A property of the UserDetails object which will be used as salt by a password encoder. Typically something like "username" might be used. + + +[[nsa-user-service]] +===== +Creates an in-memory UserDetailsService from a properties file or a list of "user" child elements. Usernames are converted to lower-case internally to allow for case-insensitive lookups, so this should not be used if case-sensitivity is required. + + +[[nsa-user-service-attributes]] +====== Attributes + + +[[nsa-user-service-id]] +* **id** +A bean identifier, used for referring to the bean elsewhere in the context. + + +[[nsa-user-service-properties]] +* **properties** +The location of a Properties file where each line is in the format of + ++ + +[source] +---- +username=password,grantedAuthority[,grantedAuthority][,enabled|disabled] +---- + + + + +[[nsa-user-service-children]] +====== Child Elements of + + +* <> + + + +[[nsa-user]] +===== +Represents a user in the application. + + +[[nsa-user-parents]] +====== Parent Elements of + + +* <> + + + +[[nsa-user-attributes]] +====== Attributes + + +[[nsa-user-authorities]] +* **authorities** +One of more authorities granted to the user. Separate authorities with a comma (but no space). For example, "ROLE_USER,ROLE_ADMINISTRATOR" + + +[[nsa-user-disabled]] +* **disabled** +Can be set to "true" to mark an account as disabled and unusable. + + +[[nsa-user-locked]] +* **locked** +Can be set to "true" to mark an account as locked and unusable. + + +[[nsa-user-name]] +* **name** +The username assigned to the user. + + +[[nsa-user-password]] +* **password** +The password assigned to the user. This may be hashed if the corresponding authentication provider supports hashing (remember to set the "hash" attribute of the "user-service" element). This attribute be omitted in the case where the data will not be used for authentication, but only for accessing authorities. If omitted, the namespace will generate a random value, preventing its accidental use for authentication. Cannot be empty. + + +[[nsa-method-security]] +==== Method Security + + +[[nsa-global-method-security]] +===== +This element is the primary means of adding support for securing methods on Spring Security beans. Methods can be secured by the use of annotations (defined at the interface or class level) or by defining a set of pointcuts as child elements, using AspectJ syntax. + + +[[nsa-global-method-security-attributes]] +====== Attributes + + +[[nsa-global-method-security-access-decision-manager-ref]] +* **access-decision-manager-ref** +Method security uses the same `AccessDecisionManager` configuration as web security, but this can be overridden using this attribute. By default an AffirmativeBased implementation is used for with a RoleVoter and an AuthenticatedVoter. + + +[[nsa-global-method-security-authentication-manager-ref]] +* **authentication-manager-ref** +A reference to an `AuthenticationManager` that should be used for method security. + + +[[nsa-global-method-security-jsr250-annotations]] +* **jsr250-annotations** +Specifies whether JSR-250 style attributes are to be used (for example "RolesAllowed"). This will require the javax.annotation.security classes on the classpath. Setting this to true also adds a `Jsr250Voter` to the `AccessDecisionManager`, so you need to make sure you do this if you are using a custom implementation and want to use these annotations. + + +[[nsa-global-method-security-metadata-source-ref]] +* **metadata-source-ref** +An external `MethodSecurityMetadataSource` instance can be supplied which will take priority over other sources (such as the default annotations). + + +[[nsa-global-method-security-mode]] +* **mode** +This attribute can be set to "aspectj" to specify that AspectJ should be used instead of the default Spring AOP. Secured methods must be woven with the `AnnotationSecurityAspect` from the `spring-security-aspects` module. + +It is important to note that AspectJ follows Java's rule that annotations on interfaces are not inherited. This means that methods that define the Security annotaitons on the interface will not be secured. Instead, you must place the Security annotation on the class when using AspectJ. + + +[[nsa-global-method-security-order]] +* **order** +Allows the advice "order" to be set for the method security interceptor. + + +[[nsa-global-method-security-pre-post-annotations]] +* **pre-post-annotations** +Specifies whether the use of Spring Security's pre and post invocation annotations (@PreFilter, @PreAuthorize, @PostFilter, @PostAuthorize) should be enabled for this application context. Defaults to "disabled". + + +[[nsa-global-method-security-proxy-target-class]] +* **proxy-target-class** +If true, class based proxying will be used instead of interface based proxying. + + +[[nsa-global-method-security-run-as-manager-ref]] +* **run-as-manager-ref** +A reference to an optional `RunAsManager` implementation which will be used by the configured `MethodSecurityInterceptor` + + +[[nsa-global-method-security-secured-annotations]] +* **secured-annotations** +Specifies whether the use of Spring Security's @Secured annotations should be enabled for this application context. Defaults to "disabled". + + +[[nsa-global-method-security-children]] +====== Child Elements of + + +* <> +* <> +* <> +* <> + + + +[[nsa-after-invocation-provider]] +===== +This element can be used to decorate an `AfterInvocationProvider` for use by the security interceptor maintained by the `` namespace. You can define zero or more of these within the `global-method-security` element, each with a `ref` attribute pointing to an `AfterInvocationProvider` bean instance within your application context. + + +[[nsa-after-invocation-provider-parents]] +====== Parent Elements of + + +* <> + + + +[[nsa-after-invocation-provider-attributes]] +====== Attributes + + +[[nsa-after-invocation-provider-ref]] +* **ref** +Defines a reference to a Spring bean that implements ` AfterInvocationProvider`. + + +[[nsa-pre-post-annotation-handling]] +===== +Allows the default expression-based mechanism for handling Spring Security's pre and post invocation annotations (@PreFilter, @PreAuthorize, @PostFilter, @PostAuthorize) to be replace entirely. Only applies if these annotations are enabled. + + +[[nsa-pre-post-annotation-handling-parents]] +====== Parent Elements of + + +* <> + + + +[[nsa-pre-post-annotation-handling-children]] +====== Child Elements of + + +* <> +* <> +* <> + + + +[[nsa-invocation-attribute-factory]] +===== +Defines the PrePostInvocationAttributeFactory instance which is used to generate pre and post invocation metadata from the annotated methods. + + +[[nsa-invocation-attribute-factory-parents]] +====== Parent Elements of + + +* <> + + + +[[nsa-invocation-attribute-factory-attributes]] +====== Attributes + + +[[nsa-invocation-attribute-factory-ref]] +* **ref** +Defines a reference to a Spring bean Id. + + +[[nsa-post-invocation-advice]] +===== +Customizes the `PostInvocationAdviceProvider` with the ref as the `PostInvocationAuthorizationAdvice` for the element. + + +[[nsa-post-invocation-advice-parents]] +====== Parent Elements of + + +* <> + + + +[[nsa-post-invocation-advice-attributes]] +====== Attributes + + +[[nsa-post-invocation-advice-ref]] +* **ref** +Defines a reference to a Spring bean Id. + + +[[nsa-pre-invocation-advice]] +===== +Customizes the `PreInvocationAuthorizationAdviceVoter` with the ref as the `PreInvocationAuthorizationAdviceVoter` for the element. + + +[[nsa-pre-invocation-advice-parents]] +====== Parent Elements of + + +* <> + + + +[[nsa-pre-invocation-advice-attributes]] +====== Attributes + + +[[nsa-pre-invocation-advice-ref]] +* **ref** +Defines a reference to a Spring bean Id. + + +[[nsa-protect-pointcut]] +===== Securing Methods using +`` +Rather than defining security attributes on an individual method or class basis using the `@Secured` annotation, you can define cross-cutting security constraints across whole sets of methods and interfaces in your service layer using the `` element. You can find an example in the <>. + + +[[nsa-protect-pointcut-parents]] +====== Parent Elements of + + +* <> + + + +[[nsa-protect-pointcut-attributes]] +====== Attributes + + +[[nsa-protect-pointcut-access]] +* **access** +Access configuration attributes list that applies to all methods matching the pointcut, e.g. "ROLE_A,ROLE_B" + + +[[nsa-protect-pointcut-expression]] +* **expression** +An AspectJ expression, including the 'execution' keyword. For example, 'execution(int com.foo.TargetObject.countLength(String))' (without the quotes). + + +[[nsa-intercept-methods]] +===== +Can be used inside a bean definition to add a security interceptor to the bean and set up access configuration attributes for the bean's methods + + +[[nsa-intercept-methods-attributes]] +====== Attributes + + +[[nsa-intercept-methods-access-decision-manager-ref]] +* **access-decision-manager-ref** +Optional AccessDecisionManager bean ID to be used by the created method security interceptor. + + +[[nsa-intercept-methods-children]] +====== Child Elements of + + +* <> + + + +[[nsa-method-security-metadata-source]] +===== +Creates a MethodSecurityMetadataSource instance + + +[[nsa-method-security-metadata-source-attributes]] +====== Attributes + + +[[nsa-method-security-metadata-source-id]] +* **id** +A bean identifier, used for referring to the bean elsewhere in the context. + + +[[nsa-method-security-metadata-source-use-expressions]] +* **use-expressions** +Enables the use of expressions in the 'access' attributes in elements rather than the traditional list of configuration attributes. Defaults to 'false'. If enabled, each attribute should contain a single boolean expression. If the expression evaluates to 'true', access will be granted. + + +[[nsa-method-security-metadata-source-children]] +====== Child Elements of + + +* <> + + + +[[nsa-protect]] +===== +Defines a protected method and the access control configuration attributes that apply to it. We strongly advise you NOT to mix "protect" declarations with any services provided "global-method-security". + + +[[nsa-protect-parents]] +====== Parent Elements of + + +* <> +* <> + + + +[[nsa-protect-attributes]] +====== Attributes + + +[[nsa-protect-access]] +* **access** +Access configuration attributes list that applies to the method, e.g. "ROLE_A,ROLE_B". + + +[[nsa-protect-method]] +* **method** +A method name + + +[[nsa-ldap]] +==== LDAP Namespace Options +LDAP is covered in some details in <>. We will expand on that here with some explanation of how the namespace options map to Spring beans. The LDAP implementation uses Spring LDAP extensively, so some familiarity with that project's API may be useful. + + +[[nsa-ldap-server]] +===== Defining the LDAP Server using the +`` Element +This element sets up a Spring LDAP `ContextSource` for use by the other LDAP beans, defining the location of the LDAP server and other information (such as a username and password, if it doesn't allow anonymous access) for connecting to it. It can also be used to create an embedded server for testing. Details of the syntax for both options are covered in the <>. The actual `ContextSource` implementation is `DefaultSpringSecurityContextSource` which extends Spring LDAP's `LdapContextSource` class. The `manager-dn` and `manager-password` attributes map to the latter's `userDn` and `password` properties respectively. + +If you only have one server defined in your application context, the other LDAP namespace-defined beans will use it automatically. Otherwise, you can give the element an "id" attribute and refer to it from other namespace beans using the `server-ref` attribute. This is actually the bean `id` of the `ContextSource` instance, if you want to use it in other traditional Spring beans. + + +[[nsa-ldap-server-attributes]] +====== Attributes + + +[[nsa-ldap-server-id]] +* **id** +A bean identifier, used for referring to the bean elsewhere in the context. + + +[[nsa-ldap-server-ldif]] +* **ldif** +Explicitly specifies an ldif file resource to load into an embedded LDAP server. The ldiff is should be a Spring resource pattern (i.e. classpath:init.ldiff). The default is classpath*:*.ldiff + + +[[nsa-ldap-server-manager-dn]] +* **manager-dn** +Username (DN) of the "manager" user identity which will be used to authenticate to a (non-embedded) LDAP server. If omitted, anonymous access will be used. + + +[[nsa-ldap-server-manager-password]] +* **manager-password** +The password for the manager DN. This is required if the manager-dn is specified. + + +[[nsa-ldap-server-port]] +* **port** +Specifies an IP port number. Used to configure an embedded LDAP server, for example. The default value is 33389. + + +[[nsa-ldap-server-root]] +* **root** +Optional root suffix for the embedded LDAP server. Default is "dc=springframework,dc=org" + + +[[nsa-ldap-server-url]] +* **url** +Specifies the ldap server URL when not using the embedded LDAP server. + + +[[nsa-ldap-authentication-provider]] +===== +This element is shorthand for the creation of an `LdapAuthenticationProvider` instance. By default this will be configured with a `BindAuthenticator` instance and a `DefaultAuthoritiesPopulator`. As with all namespace authentication providers, it must be included as a child of the `authentication-provider` element. + + +[[nsa-ldap-authentication-provider-parents]] +====== Parent Elements of + + +* <> + + + +[[nsa-ldap-authentication-provider-attributes]] +====== Attributes + + +[[nsa-ldap-authentication-provider-group-role-attribute]] +* **group-role-attribute** +The LDAP attribute name which contains the role name which will be used within Spring Security. Maps to the `DefaultLdapAuthoritiesPopulator`'s `groupRoleAttribute` property. Defaults to "cn". + + +[[nsa-ldap-authentication-provider-group-search-base]] +* **group-search-base** +Search base for group membership searches. Maps to the `DefaultLdapAuthoritiesPopulator`'s `groupSearchBase` constructor argument. Defaults to "" (searching from the root). + + +[[nsa-ldap-authentication-provider-group-search-filter]] +* **group-search-filter** +Group search filter. Maps to the `DefaultLdapAuthoritiesPopulator`'s `groupSearchFilter` property. Defaults to (uniqueMember={0}). The substituted parameter is the DN of the user. + + +[[nsa-ldap-authentication-provider-role-prefix]] +* **role-prefix** +A non-empty string prefix that will be added to role strings loaded from persistent. Maps to the `DefaultLdapAuthoritiesPopulator`'s `rolePrefix` property. Defaults to "ROLE_". Use the value "none" for no prefix in cases where the default is non-empty. + + +[[nsa-ldap-authentication-provider-server-ref]] +* **server-ref** +The optional server to use. If omitted, and a default LDAP server is registered (using with no Id), that server will be used. + + +[[nsa-ldap-authentication-provider-user-context-mapper-ref]] +* **user-context-mapper-ref** +Allows explicit customization of the loaded user object by specifying a UserDetailsContextMapper bean which will be called with the context information from the user's directory entry + + +[[nsa-ldap-authentication-provider-user-details-class]] +* **user-details-class** +Allows the objectClass of the user entry to be specified. If set, the framework will attempt to load standard attributes for the defined class into the returned UserDetails object + + +[[nsa-ldap-authentication-provider-user-dn-pattern]] +* **user-dn-pattern** +If your users are at a fixed location in the directory (i.e. you can work out the DN directly from the username without doing a directory search), you can use this attribute to map directly to the DN. It maps directly to the `userDnPatterns` property of `AbstractLdapAuthenticator`. The value is a specific pattern used to build the user's DN, for example "uid={0},ou=people". The key "{0}" must be present and will be substituted with the username. + + +[[nsa-ldap-authentication-provider-user-search-base]] +* **user-search-base** +Search base for user searches. Defaults to "". Only used with a 'user-search-filter'. + ++ + +If you need to perform a search to locate the user in the directory, then you can set these attributes to control the search. The `BindAuthenticator` will be configured with a `FilterBasedLdapUserSearch` and the attribute values map directly to the first two arguments of that bean's constructor. If these attributes aren't set and no `user-dn-pattern` has been supplied as an alternative, then the default search values of `user-search-filter="(uid={0})"` and `user-search-base=""` will be used. + + +[[nsa-ldap-authentication-provider-user-search-filter]] +* **user-search-filter** +The LDAP filter used to search for users (optional). For example "(uid={0})". The substituted parameter is the user's login name. + ++ + +If you need to perform a search to locate the user in the directory, then you can set these attributes to control the search. The `BindAuthenticator` will be configured with a `FilterBasedLdapUserSearch` and the attribute values map directly to the first two arguments of that bean's constructor. If these attributes aren't set and no `user-dn-pattern` has been supplied as an alternative, then the default search values of `user-search-filter="(uid={0})"` and `user-search-base=""` will be used. + + +[[nsa-ldap-authentication-provider-children]] +====== Child Elements of + + +* <> + + + +[[nsa-password-compare]] +===== +This is used as child element to `` and switches the authentication strategy from `BindAuthenticator` to `PasswordComparisonAuthenticator`. + + +[[nsa-password-compare-parents]] +====== Parent Elements of + + +* <> + + + +[[nsa-password-compare-attributes]] +====== Attributes + + +[[nsa-password-compare-hash]] +* **hash** +Defines the hashing algorithm used on user passwords. We recommend strongly against using MD4, as it is a very weak hashing algorithm. + + +[[nsa-password-compare-password-attribute]] +* **password-attribute** +The attribute in the directory which contains the user password. Defaults to "userPassword". + + +[[nsa-password-compare-children]] +====== Child Elements of + + +* <> + + + +[[nsa-ldap-user-service]] +===== +This element configures an LDAP `UserDetailsService`. The class used is `LdapUserDetailsService` which is a combination of a `FilterBasedLdapUserSearch` and a `DefaultLdapAuthoritiesPopulator`. The attributes it supports have the same usage as in ``. + + +[[nsa-ldap-user-service-attributes]] +====== Attributes + + +[[nsa-ldap-user-service-cache-ref]] +* **cache-ref** +Defines a reference to a cache for use with a UserDetailsService. + + +[[nsa-ldap-user-service-group-role-attribute]] +* **group-role-attribute** +The LDAP attribute name which contains the role name which will be used within Spring Security. Defaults to "cn". + + +[[nsa-ldap-user-service-group-search-base]] +* **group-search-base** +Search base for group membership searches. Defaults to "" (searching from the root). + + +[[nsa-ldap-user-service-group-search-filter]] +* **group-search-filter** +Group search filter. Defaults to (uniqueMember={0}). The substituted parameter is the DN of the user. + + +[[nsa-ldap-user-service-id]] +* **id** +A bean identifier, used for referring to the bean elsewhere in the context. + + +[[nsa-ldap-user-service-role-prefix]] +* **role-prefix** +A non-empty string prefix that will be added to role strings loaded from persistent storage (e.g. "ROLE_"). Use the value "none" for no prefix in cases where the default is non-empty. + + +[[nsa-ldap-user-service-server-ref]] +* **server-ref** +The optional server to use. If omitted, and a default LDAP server is registered (using with no Id), that server will be used. + + +[[nsa-ldap-user-service-user-context-mapper-ref]] +* **user-context-mapper-ref** +Allows explicit customization of the loaded user object by specifying a UserDetailsContextMapper bean which will be called with the context information from the user's directory entry + + +[[nsa-ldap-user-service-user-details-class]] +* **user-details-class** +Allows the objectClass of the user entry to be specified. If set, the framework will attempt to load standard attributes for the defined class into the returned UserDetails object + + +[[nsa-ldap-user-service-user-search-base]] +* **user-search-base** +Search base for user searches. Defaults to "". Only used with a 'user-search-filter'. + + +[[nsa-ldap-user-service-user-search-filter]] +* **user-search-filter** +The LDAP filter used to search for users (optional). For example "(uid={0})". The substituted parameter is the user's login name. + + +[[appendix-dependencies]] +=== Spring Security Dependencies +This appendix provides a reference of the modules in Spring Security and the additional dependencies that they require in order to function in a running application. We don't include dependenices that are only used when building or testing Spring Security itself. Nor do we include transitive dependencies which are required by external dependencies. + +The version of Spring required is listed on the project website, so the specific versions are omitted for Spring dependencies below. Note that some of the dependencies listed as"optional" below may still be required for other non-security functionality in a Spring application. Also dependencies listed as "optional" may not actually be marked as such in the project's Maven pom files if they are used in most applications. They are"optional" only in the sense that you don't need them unless you are using the specified functionality. + +Where a module depends on another Spring Security module, the non-optional dependencies of the module it depends on are also assumed to be required and are not listed separately. + + +==== spring-security-core + +The core module must be included in any project using Spring Security. + +.Core Depenendencies +|=== +| Dependency | Version | Description + +| aopalliance +| 1.0 +| Required for method security implementation. + +| ehcache +| 1.6.2 +| Required if the ehcache-based user cache implementation is used (optional). + +| spring-aop +| +| Method security is based on Spring AOP + +| spring-beans +| +| Required for Spring configuration + +| spring-expression +| +| Required for expression-based method security (optional) + +| spring-jdbc +| +| Required if using a database to store user data (optional). + +| spring-tx +| +| Required if using a database to store user data (optional). + +| aspectjrt +| 1.6.10 +| Required if using AspectJ support (optional). + +| jsr250-api +| 1.0 +| Required if you are using JSR-250 method-security annotations (optional). +|=== + +==== spring-security-remoting +This module is typically required in web applications which use the Servlet API. + +.Remoting Dependencies +|=== +| Dependency | Version | Description + +| spring-security-core +| +| + +| spring-web +| +| Required for clients which use HTTP remoting support. +|=== + +==== spring-security-web +This module is typically required in web applications which use the Servlet API. + +.Web Dependencies +|=== +| Dependency | Version | Description + +| spring-security-core +| +| + +| spring-web +| +| Spring web support classes are used extensively. + +| spring-jdbc +| +| Required for JDBC-based persistent remember-me token repository (optional). + +| spring-tx +| +| Required by remember-me persistent token repository implementations (optional). +|=== + +==== spring-security-ldap +This module is only required if you are using LDAP authentication. + +.LDAP Dependencies +|=== +| Dependency | Version | Description + +| spring-security-core +| +| + +| spring-ldap-core +| 1.3.0 +| LDAP support is based on Spring LDAP. + +| spring-tx +| +| Data exception classes are required. + +| apache-ds footnote:[The modules `apacheds-core`, `apacheds-core-entry`, `apacheds-protocol-shared`, `apacheds-protocol-ldap` and `apacheds-server-jndi` are required. +] +| 1.5.5 +| Required if you are using an embedded LDAP server (optional). + +| shared-ldap +| 0.9.15 +| Required if you are using an embedded LDAP server (optional). + +| ldapsdk +| 4.1 +| Mozilla LdapSDK. Used for decoding LDAP password policy controls if you are using password-policy functionality with OpenLDAP, for example. +|=== + + +==== spring-security-config +This module is required if you are using Spring Security namespace configuration. + +.Config Dependencies +|=== +| Dependency | Version | Description + +| spring-security-core +| +| + +| spring-security-web +| +| Required if you are using any web-related namespace configuration (optional). + +| spring-security-ldap +| +| Required if you are using the LDAP namespace options (optional). + +| spring-security-openid +| +| Required if you are using OpenID authentication (optional). + +| aspectjweaver +| 1.6.10 +| Required if using the protect-pointcut namespace syntax (optional). +|=== + + +==== spring-security-acl +The ACL module. + +.ACL Dependencies +|=== +| Dependency | Version | Description + +| spring-security-core +| +| + +| ehcache +| 1.6.2 +| Required if the ehcache-based ACL cache implementation is used (optional if you are using your own implementation). + +| spring-jdbc +| +| Required if you are using the default JDBC-based AclService (optional if you implement your own). + +| spring-tx +| +| Required if you are using the default JDBC-based AclService (optional if you implement your own). +|=== + +==== spring-security-cas +The CAS module provides integration with JA-SIG CAS. + +.CAS Dependencies +|=== +| Dependency | Version | Description + +| spring-security-core +| +| + +| spring-security-web +| +| + +| cas-client-core +| 3.1.12 +| The JA-SIG CAS Client. This is the basis of the Spring Security integration. + +| ehcache +| 1.6.2 +| Required if you are using the ehcache-based ticket cache (optional). +|=== + +==== spring-security-openid +The OpenID module. + +.OpenID Dependencies +|=== +| Dependency | Version | Description + +| spring-security-core +| +| + +| spring-security-web +| +| + +| openid4java-nodeps +| 0.9.6 +| Spring Security's OpenID integration uses OpenID4Java. + +| httpclient +| 4.1.1 +| openid4java-nodeps depends on HttpClient 4. + +| guice +| 2.0 +| openid4java-nodeps depends on Guice 2. +|=== + +==== spring-security-taglibs +Provides Spring Security's JSP tag implementations. + +.Taglib Dependencies +|=== +| Dependency | Version | Description + +| spring-security-core +| +| + +| spring-security-web +| +| + +| spring-security-acl +| +| Required if you are using the `accesscontrollist` tag or `hasPermission()` expressions with ACLs (optional). + +| spring-expression +| +| Required if you are using SPEL expressions in your tag access constraints. +|=== diff --git a/docs/manual/src/docbook/anon-auth-provider.xml b/docs/manual/src/docbook/anon-auth-provider.xml deleted file mode 100644 index 4890f5d33f..0000000000 --- a/docs/manual/src/docbook/anon-auth-provider.xml +++ /dev/null @@ -1,138 +0,0 @@ - - - Anonymous Authentication - -
- - Overview - - It's generally considered good security practice to adopt a - deny-by-default where you explicitly specify what is allowed and disallow - everything else. Defining what is accessible to unauthenticated users is a similar - situation, particularly for web applications. Many sites require that users must be - authenticated for anything other than a few URLs (for example the home and login pages). - In this case it is easiest to define access configuration attributes for these specific - URLs rather than have for every secured resource. Put differently, sometimes it is nice - to say ROLE_SOMETHING is required by default and only allow certain - exceptions to this rule, such as for login, logout and home pages of an application. You - could also omit these pages from the filter chain entirely, thus bypassing the access - control checks, but this may be undesirable for other reasons, particularly if the pages - behave differently for authenticated users. - This is what we mean by anonymous authentication. Note that there is no real - conceptual difference between a user who is anonymously authenticated and - an unauthenticated user. Spring Security's anonymous authentication just gives you a - more convenient way to configure your access-control attributes. Calls to servlet API - calls such as getCallerPrincipal, for example, will still - return null even though there is actually an anonymous authentication object in the - SecurityContextHolder. - There are other situations where anonymous authentication is useful, such as when an - auditing interceptor queries the SecurityContextHolder to - identify which principal was responsible for a given operation. Classes can be authored - more robustly if they know the SecurityContextHolder always - contains an Authentication object, and never - null. -
-
- - Configuration - - Anonymous authentication support is provided automatically when using the HTTP - configuration Spring Security 3.0 and can be customized (or disabled) using the - <anonymous> element. You don't need to configure the beans - described here unless you are using traditional bean configuration. - Three classes that together provide the anonymous authentication feature. - AnonymousAuthenticationToken is an implementation of - Authentication, and stores the - GrantedAuthoritys which apply to the anonymous principal. - There is a corresponding AnonymousAuthenticationProvider, which is - chained into the ProviderManager so that - AnonymousAuthenticationTokens are accepted. Finally, there is an - AnonymousAuthenticationFilter, which is chained after the normal - authentication mechanisms and automatically adds an - AnonymousAuthenticationToken to the - SecurityContextHolder if there is no existing - Authentication held there. The definition of the filter - and authentication provider appears as follows: - - - - - - - - -]]> - - The key is shared between the filter and authentication provider, - so that tokens created by the former are accepted by the latter - The use of the key property should not be regarded as providing - any real security here. It is merely a book-keeping exercise. If you are sharing a - ProviderManager which contains an - AnonymousAuthenticationProvider in a scenario where it is - possible for an authenticating client to construct the - Authentication object (such as with RMI invocations), - then a malicious client could submit an - AnonymousAuthenticationToken which it had created itself - (with chosen username and authority list). If the key is - guessable or can be found out, then the token would be accepted by the anonymous - provider. This isn't a problem with normal usage but if you are using RMI you would - be best to use a customized ProviderManager which omits the - anonymous provider rather than sharing the one you use for your HTTP authentication - mechanisms. - . The userAttribute is expressed in the form of - usernameInTheAuthenticationToken,grantedAuthority[,grantedAuthority]. - This is the same syntax as used after the equals sign for - InMemoryDaoImpl's userMap property. - As explained earlier, the benefit of anonymous authentication is that all URI patterns - can have security applied to them. For example: - - - - - - - - - - - - " + - -]]> - -
-
- <interfacename>AuthenticationTrustResolver</interfacename> - Rounding out the anonymous authentication discussion is the - AuthenticationTrustResolver interface, with its - corresponding AuthenticationTrustResolverImpl implementation. This - interface provides an isAnonymous(Authentication) method, which - allows interested classes to take into account this special type of authentication - status. The ExceptionTranslationFilter uses this interface in - processing AccessDeniedExceptions. If an - AccessDeniedException is thrown, and the authentication is of an - anonymous type, instead of throwing a 403 (forbidden) response, the filter will instead - commence the AuthenticationEntryPoint so the principal - can authenticate properly. This is a necessary distinction, otherwise principals would - always be deemed authenticated and never be given an opportunity to login - via form, basic, digest or some other normal authentication mechanism. - You will often see the ROLE_ANONYMOUS attribute in the above - interceptor configuration replaced with IS_AUTHENTICATED_ANONYMOUSLY, - which is effectively the same thing when defining access controls. This is an example of - the use of the AuthenticatedVoter which we will see in the authorization chapter. It uses an - AuthenticationTrustResolver to process this particular - configuration attribute and grant access to anonymous users. The - AuthenticatedVoter approach is more powerful, since it allows you - to differentiate between anonymous, remember-me and fully-authenticated users. If you - don't need this functionality though, then you can stick with - ROLE_ANONYMOUS, which will be processed by Spring Security's standard - RoleVoter. -
-
diff --git a/docs/manual/src/docbook/appendix-db-schema.xml b/docs/manual/src/docbook/appendix-db-schema.xml deleted file mode 100644 index 2cfe5a94a3..0000000000 --- a/docs/manual/src/docbook/appendix-db-schema.xml +++ /dev/null @@ -1,197 +0,0 @@ - - - - Security Database Schema - - There are various database schema used by the framework and this appendix provides a - single reference point to them all. You only need to provide the tables for the areas of - functonality you require. - DDL statements are given for the HSQLDB database. You can use these as a guideline for - defining the schema for the database you are using. -
- User Schema - The standard JDBC implementation of the - UserDetailsService (JdbcDaoImpl) - requires tables to load the password, account status (enabled or disabled) and a list of - authorities (roles) for the - user. - create table users( - username varchar_ignorecase(50) not null primary key, - password varchar_ignorecase(50) not null, - enabled boolean not null); - - create table authorities ( - username varchar_ignorecase(50) not null, - authority varchar_ignorecase(50) not null, - constraint fk_authorities_users foreign key(username) references users(username)); - create unique index ix_auth_username on authorities (username,authority); - -
- Group Authorities - Spring Security 2.0 introduced support for group authorities in - JdbcDaoImpl. The table structure if groups are enabled is as - follows: -create table groups ( - id bigint generated by default as identity(start with 0) primary key, - group_name varchar_ignorecase(50) not null); - -create table group_authorities ( - group_id bigint not null, - authority varchar(50) not null, - constraint fk_group_authorities_group foreign key(group_id) references groups(id)); - -create table group_members ( - id bigint generated by default as identity(start with 0) primary key, - username varchar(50) not null, - group_id bigint not null, - constraint fk_group_members_group foreign key(group_id) references groups(id)); - - Remember that these tables are only required if you are using the provided JDBC - UserDetailsService implementation. If you write your - own or choose to implement AuthenticationProvider - without a UserDetailsService, then you have complete - freedom over how you store the data, as long as the interface contract is - satisfied. -
-
-
- Persistent Login (Remember-Me) Schema - This table is used to store data used by the more secure persistent token remember-me - implementation. If you are using JdbcTokenRepositoryImpl either - directly or through the namespace, then you will need this table. - -create table persistent_logins ( - username varchar(64) not null, - series varchar(64) primary key, - token varchar(64) not null, - last_used timestamp not null); - -
-
- ACL Schema - There are four tables used by the Spring Security ACL implementation. - - acl_sid stores the security identities recognised by the - ACL system. These can be unique principals or authorities which may apply to - multiple principals. - - - acl_class defines the domain object types to which ACLs - apply. The class column stores the Java class name of the - object. - - - acl_object_identity stores the object identity definitions - of specific domai objects. - - - acl_entry stores the ACL permissions which apply to a - specific object identity and security identity. - - - It is assumed that the database will auto-generate the primary keys for each of the - identities. The JdbcMutableAclService has to be able to retrieve - these when it has created a new row in the acl_sid or - acl_class tables. It has two properties which define the SQL needed - to retrieve these values classIdentityQuery and - sidIdentityQuery. Both of these default to call - identity() -
- Hypersonic SQL - The default schema works with the embedded HSQLDB database that is used in unit - tests within the - framework. -create table acl_sid ( - id bigint generated by default as identity(start with 100) not null primary key, - principal boolean not null, - sid varchar_ignorecase(100) not null, - constraint unique_uk_1 unique(sid,principal) ); - -create table acl_class ( - id bigint generated by default as identity(start with 100) not null primary key, - class varchar_ignorecase(100) not null, - constraint unique_uk_2 unique(class) ); - -create table acl_object_identity ( - id bigint generated by default as identity(start with 100) not null primary key, - object_id_class bigint not null, - object_id_identity bigint not null, - parent_object bigint, - owner_sid bigint not null, - entries_inheriting boolean not null, - constraint unique_uk_3 unique(object_id_class,object_id_identity), - constraint foreign_fk_1 foreign key(parent_object)references acl_object_identity(id), - constraint foreign_fk_2 foreign key(object_id_class)references acl_class(id), - constraint foreign_fk_3 foreign key(owner_sid)references acl_sid(id) ); - -create table acl_entry ( - id bigint generated by default as identity(start with 100) not null primary key, - acl_object_identity bigint not null,ace_order int not null,sid bigint not null, - mask integer not null,granting boolean not null,audit_success boolean not null, - audit_failure boolean not null, - constraint unique_uk_4 unique(acl_object_identity,ace_order), - constraint foreign_fk_4 foreign key(acl_object_identity) - references acl_object_identity(id), - constraint foreign_fk_5 foreign key(sid) references acl_sid(id) ); - - -
-
- PostgreSQL - - create table acl_sid( - id bigserial not null primary key, - principal boolean not null, - sid varchar(100) not null, - constraint unique_uk_1 unique(sid,principal)); - -create table acl_class( - id bigserial not null primary key, - class varchar(100) not null, - constraint unique_uk_2 unique(class)); - -create table acl_object_identity( - id bigserial primary key, - object_id_class bigint not null, - object_id_identity bigint not null, - parent_object bigint, - owner_sid bigint, - entries_inheriting boolean not null, - constraint unique_uk_3 unique(object_id_class,object_id_identity), - constraint foreign_fk_1 foreign key(parent_object) references acl_object_identity(id), - constraint foreign_fk_2 foreign key(object_id_class) references acl_class(id), - constraint foreign_fk_3 foreign key(owner_sid) references acl_sid(id)); - -create table acl_entry( - id bigserial primary key, - acl_object_identity bigint not null, - ace_order int not null, - sid bigint not null, - mask integer not null, - granting boolean not null, - audit_success boolean not null, - audit_failure boolean not null, - constraint unique_uk_4 unique(acl_object_identity,ace_order), - constraint foreign_fk_4 foreign key(acl_object_identity) - references acl_object_identity(id), - constraint foreign_fk_5 foreign key(sid) references acl_sid(id)); - - You will have to set the classIdentityQuery and - sidIdentityQuery properties of - JdbcMutableAclService to the following values, - respectively: - - select currval(pg_get_serial_sequence('acl_class', - 'id')) - - - select currval(pg_get_serial_sequence('acl_sid', - 'id')) - - -
-
-
diff --git a/docs/manual/src/docbook/appendix-dependencies.xml b/docs/manual/src/docbook/appendix-dependencies.xml deleted file mode 100644 index d61f74c979..0000000000 --- a/docs/manual/src/docbook/appendix-dependencies.xml +++ /dev/null @@ -1,456 +0,0 @@ - - - - - Spring Security Dependencies - - - This appendix provides a reference of the modules in Spring Security and the additional - dependencies that they require in order to function in a running application. We don't include - dependenices that are only used when building or testing Spring Security itself. Nor do we include - transitive dependencies which are required by external dependencies. - - The version of Spring required is listed on the project website, so the specific versions - are omitted for Spring dependencies below. Note that some of the dependencies listed as - optional below may still be required for other non-security functionality in - a Spring application. Also dependencies listed as optional may not actually be marked - as such in the project's Maven pom files if they are used in most applications. They are - optional only in the sense that you don't need them unless you are using the - specified functionality. - Where a module depends on another Spring Security module, the non-optional dependencies of the - module it depends on are also assumed to be required and are not listed separately. - -
- <literal>spring-security-core</literal> - The core module must be included in any project using Spring Security. - - Core Depenendencies - - - - - - - Dependency - Version - Description - - - - - aopalliance - 1.0 - Required for method security implementation. - - - ehcache - 1.6.2 - Required if the ehcache-based user cache implementation is used (optional). - - - spring-aop - - Method security is based on Spring AOP - - - spring-beans - - Required for Spring configuration - - - spring-expression - - Required for expression-based method security (optional) - - - spring-jdbc - - Required if using a database to store user data (optional). - - - spring-tx - - Required if using a database to store user data (optional). - - - aspectjrt - 1.6.10 - Required if using AspectJ support (optional). - - - jsr250-api - 1.0 - Required if you are using JSR-250 method-security annotations (optional). - - - -
-
- -
- -
- <literal>spring-security-remoting</literal> - This module is typically required in web applications which use the Servlet API. - - Remoting Dependencies - - - - - - - Dependency - Version - Description - - - - - spring-security-core - - - - - spring-web - - Required for clients which use HTTP remoting support. - - - -
-
-
- -
- <literal>spring-security-web</literal> - This module is typically required in web applications which use the Servlet API. - - Web Dependencies - - - - - - - Dependency - Version - Description - - - - - spring-security-core - - - - - spring-web - - Spring web support classes are used extensively. - - - spring-jdbc - - Required for JDBC-based persistent remember-me token repository (optional). - - - spring-tx - - Required by remember-me persistent token repository implementations (optional). - - - -
-
-
- -
- <literal>spring-security-ldap</literal> - This module is only required if you are using LDAP authentication. - - LDAP Dependencies - - - - - - - Dependency - Version - Description - - - - - spring-security-core - - - - - spring-ldap-core - 1.3.0 - LDAP support is based on Spring LDAP. - - - spring-tx - - Data exception classes are required. - - - apache-ds The modules apacheds-core, - apacheds-core-entry, apacheds-protocol-shared, - apacheds-protocol-ldap and apacheds-server-jndi are required. - - 1.5.5 - Required if you are using an embedded LDAP server (optional). - - - shared-ldap - 0.9.15 - Required if you are using an embedded LDAP server (optional). - - - ldapsdk - 4.1 - - Mozilla LdapSDK. Used for decoding LDAP password policy controls if you are - using password-policy functionality with OpenLDAP, for example. - - - - - -
-
-
- -
- <literal>spring-security-config</literal> - This module is required if you are using Spring Security namespace configuration. - - Config Dependencies - - - - - - - Dependency - Version - Description - - - - - spring-security-core - - - - - spring-security-web - - Required if you are using any web-related namespace configuration (optional). - - - spring-security-ldap - - Required if you are using the LDAP namespace options (optional). - - - spring-security-openid - - Required if you are using OpenID authentication (optional). - - - aspectjweaver - 1.6.10 - Required if using the protect-pointcut namespace syntax (optional). - - - -
-
-
- -
- <literal>spring-security-acl</literal> - The ACL module. - - ACL Dependencies - - - - - - - Dependency - Version - Description - - - - - spring-security-core - - - - - ehcache - 1.6.2 - Required if the ehcache-based ACL cache implementation is used (optional if you are using your own implementation). - - - spring-jdbc - - Required if you are using the default JDBC-based AclService (optional if you implement your own). - - - spring-tx - - Required if you are using the default JDBC-based AclService (optional if you implement your own). - - - -
-
-
- -
- <literal>spring-security-cas</literal> - The CAS module provides integration with JA-SIG CAS. - - CAS Dependencies - - - - - - - Dependency - Version - Description - - - - - spring-security-core - - - - - spring-security-web - - - - - cas-client-core - 3.1.12 - The JA-SIG CAS Client. This is the basis of the Spring Security integration. - - - ehcache - 1.6.2 - Required if you are using the ehcache-based ticket cache (optional). - - - -
-
-
- -
- <literal>spring-security-openid</literal> - The OpenID module. - - OpenID Dependencies - - - - - - - Dependency - Version - Description - - - - - spring-security-core - - - - - spring-security-web - - - - - openid4java-nodeps - 0.9.6 - Spring Security's OpenID integration uses OpenID4Java. - - - httpclient - 4.1.1 - openid4java-nodeps depends on HttpClient 4. - - - guice - 2.0 - openid4java-nodeps depends on Guice 2. - - - -
-
-
- -
- <literal>spring-security-taglibs</literal> - Provides Spring Security's JSP tag implementations. - - Taglib Dependencies - - - - - - - Dependency - Version - Description - - - - - spring-security-core - - - - - spring-security-web - - - - - spring-security-acl - - - Required if you are using the accesscontrollist tag or - hasPermission() expressions with ACLs (optional). - - - - spring-expression - - Required if you are using SPEL expressions in your tag access constraints. - - - -
-
-
-
diff --git a/docs/manual/src/docbook/appendix-namespace.xml b/docs/manual/src/docbook/appendix-namespace.xml deleted file mode 100644 index 53b29862f0..0000000000 --- a/docs/manual/src/docbook/appendix-namespace.xml +++ /dev/null @@ -1,2293 +0,0 @@ - - - - The Security Namespace - - This appendix provides a reference to the elements available in the security namespace - and information on the underlying beans they create (a knowledge of the individual classes - and how they work together is assumed - you can find more information in the project Javadoc - and elsewhere in this document). If you haven't used the namespace before, please read the - introductory chapter on namespace configuration, as - this is intended as a supplement to the information there. Using a good quality XML editor - while editing a configuration based on the schema is recommended as this will provide - contextual information on which elements and attributes are available as well as comments - explaining their purpose. The namespace is written in RELAX NG Compact format and later converted into - an XSD schema. If you are familiar with this format, you may wish to examine the schema file directly. -
- Web Application Security -
- <literal><debug></literal> - Enables Spring Security debugging infrastructure. This will provide human-readable (multi-line) - debugging information to monitor requests coming into the security filters. This may include sensitive - information, such as request parameters or headers, and should only be used in a development - environment. -
-
- <literal><http></literal> - If you use an <http> element within your application, a - FilterChainProxy bean named "springSecurityFilterChain" is - created and the configuration within the element is used to build a filter chain within - FilterChainProxy. As of Spring Security 3.1, additional - http elements can be used to add extra filter chains - See the introductory chapter for how to set - up the mapping from your web.xml - . Some core filters are always created in a filter chain and others will be - added to the stack depending on the attributes and child elements which are present. The - positions of the standard filters are fixed (see the - filter order table in the namespace introduction), removing a common source of - errors with previous versions of the framework when users had to configure the filter - chain explicitly in the FilterChainProxy bean. You can, of course, - still do this if you need full control of the configuration. - All filters which require a reference to the - AuthenticationManager will be automatically injected with - the internal instance created by the namespace configuration (see the introductory chapter for more on the - AuthenticationManager). - Each <http> namespace block always creates an - SecurityContextPersistenceFilter, an - ExceptionTranslationFilter and a - FilterSecurityInterceptor. These are fixed and cannot be replaced - with alternatives. -
- <literal><http></literal> Attributes - The attributes on the <http> element control some of the - properties on the core filters. -
- <literal>access-decision-manager-ref</literal> - Optional attribute specifying the ID of the - AccessDecisionManager implementation which should - be used for authorizing HTTP requests. By default an - AffirmativeBased implementation is used for with a - RoleVoter and an - AuthenticatedVoter. -
-
- <literal>access-denied-page</literal> - Deprecated in favour of the access-denied-handler - child element. -
-
- <literal>authentication-manager-ref</literal> - A reference to the AuthenticationManager used for the - FilterChain created by this http element. -
-
- <literal>auto-config</literal> - Automatically registers a login form, BASIC authentication, logout - services. If set to "true", all of these capabilities are added - (although you can still customize the configuration of each by providing the respective element). If - unspecified, defaults to "false". Use of this attribute is not recommended. Use explicit - configuration elements instead to avoid confusion. - -
-
- <literal>create-session</literal> - Controls the eagerness with which an HTTP session is created by Spring Security classes. - Options include: - - - always - Spring Security will proactively create a session if one - does not exist. - - - ifRequired - Spring Security will only create a session only if one - is required (default value). - - - never - Spring Security will never create a session, but will - make use of one if the application does. - - stateless - Spring Security will not create a session and ignore the - session for obtaining a Spring Authentication. - - - -
-
- <literal>disable-url-rewriting</literal> - Prevents session IDs from being appended to URLs in the application. Clients - must use cookies if this attribute is set to true. The default is - false. -
-
- <literal>entry-point-ref</literal> - Normally the AuthenticationEntryPoint used - will be set depending on which authentication mechanisms have been configured. - This attribute allows this behaviour to be overridden by defining a customized - AuthenticationEntryPoint bean which will start - the authentication process. -
-
- <literal>jaas-api-provision</literal> - If available, runs the request as the Subject acquired from - the JaasAuthenticationToken which is implemented by - adding a JaasApiIntegrationFilter bean to the stack. - Defaults to false. -
-
- <literal>name</literal> - A bean identifier, used for referring to the bean elsewhere in the context. -
-
- <literal>once-per-request</literal> - Corresponds to the observeOncePerRequest property of - FilterSecurityInterceptor. Defaults to true. -
-
- <literal>path-type</literal> - Deprecated in favor of request-matcher. - -
-
- <literal>pattern</literal> - Defining a pattern for the http element controls the - requests which will be filtered through the list of filters which it defines. - The interpretation is dependent on the configured request-matcher. If no pattern is defined, - all requests will be matched, so the most specific patterns should be declared - first. -
-
- <literal>realm</literal> - Sets the realm name used for basic authentication (if enabled). Corresponds - to the realmName property on - BasicAuthenticationEntryPoint. -
-
- <literal>request-matcher</literal> - Defines the RequestMatcher strategy used in - the FilterChainProxy and the beans created by the - intercept-url to match incoming requests. Options are - currently ant, regex and - ciRegex, for ant, regular-expression and case-insensitive - regular-expression repsectively. A separate instance is created for each - intercept-url element using its - pattern and - method attributes. Ant paths - are matched using an AntPathRequestMatcher and regular expressions - are matched using a RegexRequestMatcher. See the Javadoc - for these classes for more details on exactly how the matching is preformed. Ant - paths are the default strategy. -
-
- <literal>request-matcher-ref</literal> - A referenece to a bean that implements RequestMatcher that - will determine if this FilterChain should be used. This is a more - powerful alternative to pattern. -
-
- <literal>security</literal> - A request pattern can be mapped to an empty filter chain, by setting this - attribute to none. No security will be applied and none of - Spring Security's features will be available. -
-
- <literal>security-context-repository-ref</literal> - Allows injection of a custom - SecurityContextRepository into the - SecurityContextPersistenceFilter. -
-
- <literal>servlet-api-provision</literal> - Provides versions of HttpServletRequest security methods - such as isUserInRole() and getPrincipal() - which are implemented by adding a - SecurityContextHolderAwareRequestFilter bean to the - stack. Defaults to true. -
-
- <literal>use-expressions</literal> - Enables EL-expressions in the access attribute, as - described in the chapter on expression-based - access-control. -
-
-
- Child Elements of <http> - - access-denied-handler - anonymous - csrf - custom-filter - expression-handler - form-login - headers - http-basic - intercept-url - jee - logout - openid-login - port-mappings - remember-me - request-cache - session-management - x509 - -
-
-
- <literal><access-denied-handler></literal> - This element allows you to set the errorPage property for the - default AccessDeniedHandler used by the - ExceptionTranslationFilter, using the - error-page attribute, or - to supply your own implementation using the - ref attribute. This is discussed - in more detail in the section on the - ExceptionTranslationFilter. -
- Parent Elements of <literal><access-denied-handler></literal> - - http - -
-
- <literal><access-denied-handler></literal> Attributes -
- <literal>error-page</literal> - The access denied page that an authenticated user will be redirected to if they request a - page which they don't have the authority to access. -
-
- <literal>ref</literal> - Defines a reference to a Spring bean of type AccessDeniedHandler - . -
-
-
-
- <literal><headers></literal> - This element allows for configuring additional (security) headers to be send with the response. - It enables easy configuration for several headers and also allows for setting custom headers through - the header element. Additional information, can be found in the - Security Headers section of the reference. - - Cache-Control, Pragma, and Expires - Can be set using the - cache-control element. This ensures that the - browser does not cache your secured pages. - Strict-Transport-Security - Can be set using the - hsts element. This ensures that the - browser automatically requests HTTPS for future requests. - X-Frame-Options - Can be set using the - frame-options element. The - X-Frame-Options - header can be used to prevent clickjacking attacks. - X-XSS-Protection - Can be set using the - xss-protection element. - The X-XSS-Protection - header can be used by browser to do basic control. - X-Content-Type-Options - Can be set using the - content-type-options element. The - X-Content-Type-Options - header prevents Internet Explorer from MIME-sniffing a response away from the declared - content-type. This also applies to Google Chrome, when downloading extensions. - - -
- Parent Elements of <literal><headers></literal> - - http - -
-
- Child Elements of <literal><headers></literal> - - cache-control - content-type-options - frame-options - header - hsts - xss-protection - -
-
-
- <literal><cache-control></literal> - Adds Cache-Control, Pragma, and Expires - headers to ensure that the browser does not cache your secured pages. -
- Parent Elements of <literal><cache-control></literal> - - headers - -
-
-
- <literal><hsts></literal> - When enabled adds the Strict-Transport-Security header to the response - for any secure request. This allows the server to instruct browsers to automatically use HTTPS for future requests. -
- <literal><hsts></literal> Attributes -
- <literal>include-sub-domains</literal> - - Specifies if subdomains should be included. Default true. - -
-
- <literal>max-age-seconds</literal> - - Specifies the maximum ammount of time the host should be considered a Known HSTS Host. Default one year. - -
-
- <literal>request-matcher-ref</literal> - - The RequestMatcher instance to be used to determine if the header should be set. Default is if HttpServletRequest.isSecure() is true. - -
-
-
- Parent Elements of <literal><hsts></literal> - - headers - -
-
-
- <literal><frame-options></literal> - When enabled adds the X-Frame-Options header to the response, this allows newer browsers to do some security - checks and prevent clickjacking attacks. -
- <literal><frame-options></literal> Attributes -
- <literal>policy</literal> - - - DENY The page cannot be displayed in a frame, regardless of - the site attempting to do so. This is the default when frame-options-policy is specified. - SAMEORIGIN The page can only be displayed in a frame on the - same origin as the page itself - ALLOW-FROM origin - The page can only be displayed in a frame on the specified origin. - - - In other words, if you specify DENY, not only will attempts to load the page in a frame fail - when loaded from other sites, attempts to do so will fail when loaded from the same site. On the - other hand, if you specify SAMEORIGIN, you can still use the page in a frame as long as the site - including it in a frame it is the same as the one serving the page. - -
-
- <literal>strategy</literal> - - Select the AllowFromStrategy to use when using the ALLOW-FROM policy. - - static Use a single static ALLOW-FROM value. The value can be set - through the value attribute. - - regexp Use a regelur expression to validate incoming requests and - if they are allowed. The regular expression can be set through the value - attribute. The request parameter used to retrieve the value to validate can be specified - using the from-parameter. - - whitelistA comma-seperated list containing the allowed domains. - The comma-seperated list can be set through the value - attribute. The request parameter used to retrieve the value to validate can be specified - using the from-parameter. - - - -
-
- <literal>ref</literal> - - Instead of using one of the predefined strategies it is also possible to use a custom AllowFromStrategy. - The reference to this bean can be specified through this ref attribute. - -
-
- <literal>value</literal> - The value to use when ALLOW-FROM is used a strategy. -
-
- <literal>from-parameter</literal> - - Specify the name of the request parameter to use when using regexp or whitelist for the ALLOW-FROM - strategy. - -
-
-
- Parent Elements of <literal><frame-options></literal> - - headers - -
-
-
- <literal><xss-protection></literal> - Adds the X-XSS-Protection header - to the response to assist in protecting against reflected / “Type-1” Cross-Site Scripting (XSS) - attacks. This is in no-way a full protection to XSS attacks! -
-
- <literal>xss-protection-enabled</literal> - Enable or Disable reflected / “Type-1” Cross-Site Scripting (XSS) protection. -
-
- <literal>xss-protection-block</literal> - When true and xss-protection-enabled is true, adds mode=block to the header. This indicates to the browser that the - page should not be loaded at all. When false and xss-protection-enabled is true, the page will still be rendered when - an reflected attack is detected but the response will be modified to protect against the attack. Note that there are - sometimes ways of bypassing this mode which can often times make blocking the page more desirable. -
-
-
- Parent Elements of <literal><xss-protection></literal> - - headers - -
-
-
- <literal><content-type-options></literal> - Add the X-Content-Type-Options header with the value of nosniff to the response. This - disables MIME-sniffing - for IE8+ and Chrome extensions. -
- Parent Elements of <literal><content-type-options></literal> - - headers - -
-
-
- <literal><header></literal> - Add additional headers to the response, both the name and value need to be specified. -
- <literal><header-attributes></literal> Attributes -
- <literal>header-name</literal> - The name of the header. -
-
- <literal>header-value</literal> - The value of the header to add. -
-
- <literal>header-ref</literal> - Reference to a custom implementation of the HeaderWriter interface. -
-
-
- Parent Elements of <literal><header></literal> - - headers - -
-
-
- <literal><anonymous></literal> - Adds an AnonymousAuthenticationFilter to the stack and an - AnonymousAuthenticationProvider. Required if you are using - the IS_AUTHENTICATED_ANONYMOUSLY attribute. -
- Parent Elements of <literal><anonymous></literal> - - http - -
-
- <literal><anonymous></literal> Attributes -
- <literal>enabled</literal> - With the default namespace setup, the anonymous "authentication" facility is automatically - enabled. You can disable it using this property. -
-
- <literal>granted-authority</literal> - The granted authority that should be assigned to the anonymous request. Commonly this is used - to assign the anonymous request particular roles, which can subsequently be used in authorization - decisions. If unset, defaults to ROLE_ANONYMOUS. -
-
- <literal>key</literal> - The key shared between the provider and filter. This generally does not need to be set. If - unset, it will default to a secure randomly generated value. This means setting this value can - improve startup time when using the anonymous functionality since secure random values can take - a while to be generated. -
-
- <literal>username</literal> - The username that should be assigned to the anonymous request. This allows the principal to - be identified, which may be important for logging and auditing. if unset, defaults to - anonymousUser. -
-
-
-
- <literal><csrf></literal> - This element will add Cross Site Request Forger (CSRF) - protection to the application. It also updates the default RequestCache - to only replay "GET" requests upon successful authentication. Additional information can be found in the Cross Site - Request Forgery (CSRF) section of the reference. -
- Parent Elements of <literal><csrf></literal> - - http - -
-
- <literal><csrf></literal> Attributes -
- <literal>token-repository-ref</literal> - The CsrfTokenRepository to use. The default is - HttpSessionCsrfTokenRepository. -
-
- <literal>request-matcher-ref</literal> - The RequestMatcher instance to be used to determine if CSRF should be applied. Default is any - HTTP method except "GET", "TRACE", "HEAD", "OPTIONS". -
-
-
-
- <literal><custom-filter></literal> - This element is used to add a filter to the filter chain. It doesn't create any - additional beans but is used to select a bean of type - javax.servlet.Filter which is already defined in the - application context and add that at a particular position in the filter chain - maintained by Spring Security. Full details can be found in the - namespace chapter. -
- Parent Elements of <literal><custom-filter></literal> - - http - -
-
- <literal><custom-filter></literal> Attributes -
- <literal>after</literal> - The filter immediately after which the custom-filter should be placed in the chain. This - feature will only be needed by advanced users who wish to mix their own filters into the - security filter chain and have some knowledge of the standard Spring Security filters. The - filter names map to specific Spring Security implementation filters. -
-
- <literal>before</literal> - The filter immediately before which the custom-filter should be placed in the chain -
-
- <literal>position</literal> - The explicit position at which the custom-filter should be placed in the chain. Use if you - are replacing a standard filter. -
-
- <literal>ref</literal> - Defines a reference to a Spring bean that implements Filter. -
-
-
-
- <literal><expression-handler></literal> - Defines the SecurityExpressionHandler instance which will be used if - expression-based access-control is enabled. A default implementation (with no ACL support) will be used - if not supplied. -
- Parent Elements of <literal><expression-handler></literal> - - global-method-security - http - -
-
- <literal><expression-handler></literal> Attributes -
- <literal>ref</literal> - Defines a reference to a Spring bean that implements SecurityExpressionHandler. -
-
-
-
- <literal><form-login></literal> - Used to add an UsernamePasswordAuthenticationFilter to the - filter stack and an LoginUrlAuthenticationEntryPoint to the - application context to provide authentication on demand. This will always take - precedence over other namespace-created entry points. If no attributes are supplied, - a login page will be generated automatically at the URL "/spring_security_login" - This feature is really just provided for convenience and is not intended for - production (where a view technology will have been chosen and can be used to - render a customized login page). The class - DefaultLoginPageGeneratingFilter is responsible for - rendering the login page and will provide login forms for both normal form login - and/or OpenID if required. - The behaviour can be customized using the - <form-login> Attributes. -
- Parent Elements of <literal><form-login></literal> - - http - -
-
- <literal><form-login></literal> Attributes -
- <literal>always-use-default-target</literal> - If set to true, the user will always start at the value given by - default-target-url, regardless - of how they arrived at the login page. Maps to the alwaysUseDefaultTargetUrl - property of UsernamePasswordAuthenticationFilter. Default value is - false. -
-
- <literal>authentication-details-source-ref</literal> - Reference to an AuthenticationDetailsSource which will be used - by the authentication filter -
-
- <literal>authentication-failure-handler-ref</literal> - Can be used as an alternative to - authentication-failure-url, - giving you full control over the navigation flow after an authentication failure. The value - should be he name of an AuthenticationFailureHandler bean in the - application context. -
-
- <literal>authentication-failure-url</literal> - Maps to the authenticationFailureUrl property of - UsernamePasswordAuthenticationFilter. Defines the URL the - browser will be redirected to on login failure. Defaults to - /spring_security_login?login_error, which will be automatically handled by - the automatic login page generator, re-rendering the login page with an error message. -
-
- <literal>authentication-success-handler-ref</literal> - This can be used as an alternative to - default-target-url - and always-use-default-target, - giving you full control over the navigation flow after a successful authentication. The value - should be the name of an AuthenticationSuccessHandler bean in - the application context. By default, an implementation of - SavedRequestAwareAuthenticationSuccessHandler is used and - injected with the default-target-url - . -
-
- <literal>default-target-url</literal> - Maps to the defaultTargetUrl property of - UsernamePasswordAuthenticationFilter. If not set, the - default value is "/" (the application root). A user will be taken to this URL - after logging in, provided they were not asked to login while attempting to - access a secured resource, when they will be taken to the originally requested - URL. -
-
- <literal>login-page</literal> - The URL that should be used to render the login page. Maps to the - loginFormUrl property of the - LoginUrlAuthenticationEntryPoint. Defaults to - "/spring_security_login". -
-
- <literal>login-processing-url</literal> - Maps to the filterProcessesUrl property of - UsernamePasswordAuthenticationFilter. The default value - is "/j_spring_security_check". -
-
- <literal>password-parameter</literal> - The name of the request parameter which contains the password. Defaults to "j_password". -
-
- <literal>username-parameter</literal> - The name of the request parameter which contains the username. Defaults to "j_username". -
-
-
-
- <literal><http-basic></literal> - Adds a BasicAuthenticationFilter and - BasicAuthenticationEntryPoint to the configuration. The - latter will only be used as the configuration entry point if form-based login is not - enabled. -
- Parent Elements of <literal><http-basic></literal> - - http - -
-
- <literal><http-basic></literal> Attributes -
- <literal>authentication-details-source-ref</literal> - Reference to an AuthenticationDetailsSource which will be used - by the authentication filter -
-
- <literal>entry-point-ref</literal> - Sets the AuthenticationEntryPoint which is used by the - BasicAuthenticationFilter. -
-
-
-
- <literal><http-firewall></literal> Element - This is a top-level element which can be used to inject a custom implementation of - HttpFirewall into the - FilterChainProxy created by the namespace. The default - implementation should be suitable for most applications. -
- <literal><http-firewall></literal> Attributes -
- <literal>ref</literal> - Defines a reference to a Spring bean that implements HttpFirewall. -
-
-
-
- <literal><intercept-url></literal> - This element is used to define the set of URL patterns that the application is - interested in and to configure how they should be handled. It is used to construct - the FilterInvocationSecurityMetadataSource used by - the FilterSecurityInterceptor. It is also responsible for - configuring a ChannelProcessingFilter if particular URLs - need to be accessed by HTTPS, for example. When matching the specified patterns - against an incoming request, the matching is done in the order in which the elements - are declared. So the most specific matches patterns should come first and the most - general should come last. -
- Parent Elements of <literal><intercept-url></literal> - - filter-invocation-definition-source - filter-security-metadata-source - http - -
-
- <literal><intercept-url></literal> Attributes -
- <literal>access</literal> - Lists the access attributes which will be stored in the - FilterInvocationSecurityMetadataSource for the - defined URL pattern/method combination. This should be a comma-separated list of - the security configuration attributes (such as role names). -
-
- <literal>filters</literal> - Can only take the value none. This will cause any matching - request to bypass the Spring Security filter chain entirely. None of the rest of - the <http> configuration will have any effect on the - request and there will be no security context available for its duration. Access - to secured methods during the request will fail. -
-
- <literal>method</literal> - The HTTP Method which will be used in combination with the pattern to match - an incoming request. If omitted, any method will match. If an identical pattern - is specified with and without a method, the method-specific match will take - precedence. -
-
- <literal>pattern</literal> - The pattern which defines the URL path. The content will depend on the - request-matcher attribute from the containing http element, - so will default to ant path syntax. -
-
- <literal>requires-channel</literal> - Can be http or https depending on whether a - particular URL pattern should be accessed over HTTP or HTTPS respectively. - Alternatively the value any can be used when there is no - preference. If this attribute is present on any - <intercept-url> element, then a - ChannelProcessingFilter will be added to the filter - stack and its additional dependencies added to the application - context. - If a <port-mappings> configuration is added, this - will be used to by the SecureChannelProcessor and - InsecureChannelProcessor beans to determine the ports - used for redirecting to HTTP/HTTPS. -
-
-
-
- <literal><jee></literal> - Adds a J2eePreAuthenticatedProcessingFilter to the filter chain to provide integration with container - authentication. -
- Parent Elements of <literal><jee></literal> - - http - -
-
- <literal><jee></literal> Attributes -
- <literal>mappable-roles</literal> - A comma-separate list of roles to look for in the incoming HttpServletRequest. -
-
- <literal>user-service-ref</literal> - A reference to a user-service (or UserDetailsService bean) Id -
-
-
-
- <literal><logout></literal> - Adds a LogoutFilter to the filter stack. This is - configured with a SecurityContextLogoutHandler. -
- Parent Elements of <literal><logout></literal> - - http - -
-
- <literal><logout></literal> Attributes -
- The <literal>delete-cookies</literal> attribute - A comma-separated list of the names of cookies which should be deleted when the user logs out. - -
-
- The <literal>invalidate-session</literal> attribute - Maps to the invalidateHttpSession of the - SecurityContextLogoutHandler. Defaults to "true", so the - session will be invalidated on logout. -
-
- The <literal>logout-success-url</literal> attribute - The destination URL which the user will be taken to after logging out. - Defaults to "/". - Setting this attribute will inject the SessionManagementFilter - with a SimpleRedirectInvalidSessionStrategy configured with - the attribute value. When an invalid session ID is submitted, the strategy will be invoked, - redirecting to the configured URL. -
-
- The <literal>logout-url</literal> attribute - The URL which will cause a logout (i.e. which will be processed by the - filter). Defaults to "/j_spring_security_logout". -
-
- The <literal>success-handler-ref</literal> attribute - May be used to supply an instance of LogoutSuccessHandler - which will be invoked to control the navigation after logging out. - -
-
-
-
- <literal><openid-login></literal> - Similar to <form-login> and has the same attributes. The - default value for login-processing-url is - "/j_spring_openid_security_check". An - OpenIDAuthenticationFilter and - OpenIDAuthenticationProvider will be registered. The latter - requires a reference to a UserDetailsService. Again, - this can be specified by id, using the user-service-ref - attribute, or will be located automatically in the application context. -
- Parent Elements of <literal><openid-login></literal> - - http - -
-
- <literal><openid-login></literal> Attributes -
- <literal>always-use-default-target</literal> - Whether the user should always be redirected to the default-target-url after login. -
-
- <literal>authentication-details-source-ref</literal> - Reference to an AuthenticationDetailsSource which will be used by the authentication filter -
-
- <literal>authentication-failure-handler-ref</literal> - Reference to an AuthenticationFailureHandler bean which should be used to handle a failed - authentication request. Should not be used in combination with authentication-failure-url as the - implementation should always deal with navigation to the subsequent destination -
-
- <literal>authentication-failure-url</literal> - The URL for the login failure page. If no login failure URL is specified, Spring Security will - automatically create a failure login URL at /spring_security_login?login_error and a corresponding - filter to render that login failure URL when requested. -
-
- <literal>authentication-success-handler-ref</literal> - Reference to an AuthenticationSuccessHandler bean which should be used to handle a successful - authentication request. Should not be used in combination with - default-target-url (or - - always-use-default-target) as the implementation should always deal with navigation - to the subsequent destination -
-
- <literal>default-target-url</literal> - The URL that will be redirected to after successful authentication, if the user's previous action - could not be resumed. This generally happens if the user visits a login page without having first requested a - secured operation that triggers authentication. If unspecified, defaults to the root of the application. -
-
- <literal>login-page</literal> - The URL for the login page. If no login URL is specified, Spring Security will automatically - create a login URL at /spring_security_login and a corresponding filter to render that login URL when requested. - -
-
- <literal>login-processing-url</literal> - The URL that the login form is posted to. If unspecified, it defaults to /j_spring_security_check. -
-
- <literal>password-parameter</literal> - The name of the request parameter which contains the password. Defaults to "j_password". -
-
- <literal>user-service-ref</literal> - A reference to a user-service (or UserDetailsService bean) Id -
-
- <literal>username-parameter</literal> - The name of the request parameter which contains the username. Defaults to "j_username". -
-
-
- Child Elements of <openid-login> - - attribute-exchange - -
-
-
- <literal><attribute-exchange></literal> - The attribute-exchange element defines the list of - attributes which should be requested from the identity provider. An example can be found - in the OpenID Support section of the namespace configuration - chapter. More than one can be used, in which case each must have an identifier-match - attribute, containing a regular expression which is matched against the supplied - OpenID identifier. This allows different attribute lists to be fetched from - different providers (Google, Yahoo etc). -
- Parent Elements of <literal><attribute-exchange></literal> - - openid-login - -
-
- <literal><attribute-exchange></literal> Attributes -
- <literal>identifier-match</literal> - A regular expression which will be compared against the claimed identity, when deciding which - attribute-exchange configuration to use during authentication. -
-
-
- Child Elements of <literal><attribute-exchange></literal> - - openid-attribute - -
-
-
- <literal><openid-attribute></literal> - Attributes used when making an OpenID AX - - Fetch Request -
- Parent Elements of <literal><openid-attribute></literal> - - attribute-exchange - -
-
- <literal><openid-attribute></literal> Attributes -
- <literal>count</literal> - Specifies the number of attributes that you wish to get back. For example, return 3 emails. - The default value is 1. -
-
- <literal>name</literal> - Specifies the name of the attribute that you wish to get back. For example, email. -
-
- <literal>required</literal> - Specifies if this attribute is required to the OP, but does not error out if the OP does not - return the attribute. Default is false. -
-
- <literal>type</literal> - Specifies the attribute type. For example, http://axschema.org/contact/email. See your OP's - documentation for valid attribute types. -
-
-
-
- <literal><port-mappings></literal> - By default, an instance of PortMapperImpl will be added to - the configuration for use in redirecting to secure and insecure URLs. This element - can optionally be used to override the default mappings which that class defines. - Each child <port-mapping> element defines a pair of - HTTP:HTTPS ports. The default mappings are 80:443 and 8080:8443. An example of - overriding these can be found in the namespace introduction. -
- Parent Elements of <literal><port-mappings></literal> - - http - -
-
- Child Elements of <literal><port-mappings></literal> - - port-mapping - -
-
-
- <literal><port-mapping></literal> - Provides a method to map http ports to https ports when forcing a redirect. -
- Parent Elements of <literal><port-mapping></literal> - - port-mappings - -
-
- <literal><port-mapping></literal> Attributes -
- <literal>http</literal> - The http port to use. -
-
- <literal>https</literal> - The https port to use. -
-
-
-
- <literal><remember-me></literal> - Adds the RememberMeAuthenticationFilter to the stack. This - in turn will be configured with either a - TokenBasedRememberMeServices, a - PersistentTokenBasedRememberMeServices or a user-specified - bean implementing RememberMeServices depending on the - attribute settings. -
- Parent Elements of <literal><remember-me></literal> - - http - -
-
- <literal><remember-me></literal> Attributes -
- <literal>authentication-success-handler-ref</literal> - Sets the authenticationSuccessHandler property on the - RememberMeAuthenticationFilter if custom navigation is required. - The value should be the name of a AuthenticationSuccessHandler - bean in the application context. -
-
- <literal>data-source-ref</literal> - A reference to a DataSource bean. If this is set, - PersistentTokenBasedRememberMeServices will be used and configured with a - JdbcTokenRepositoryImpl instance. -
-
- <literal>remember-me-parameter</literal> - The name of the request parameter which toggles remember-me authentication. Defaults to "_spring_security_remember_me". - Maps to the "parameter" property of AbstractRememberMeServices. -
-
- <literal>key</literal> - Maps to the "key" property of - AbstractRememberMeServices. Should be set to a unique - value to ensure that remember-me cookies are only valid within the one - application - This doesn't affect the use of - PersistentTokenBasedRememberMeServices, where the - tokens are stored on the server side. - . If this is not set a secure random value will be generated. Since generating secure - random values can take a while, setting this value explicitly can help improve startup times when - using the remember me functionality. -
-
- <literal>services-alias</literal> - Exports the internally defined RememberMeServices as a bean alias, - allowing it to be used by other beans in the application context. -
-
- <literal>services-ref</literal> - Allows complete control of the - RememberMeServices implementation that will be - used by the filter. The value should be the id of a bean in the application - context which implements this interface. Should also implement - LogoutHandler if a logout filter is in use. -
-
- <literal>token-repository-ref</literal> - Configures a PersistentTokenBasedRememberMeServices - but allows the use of a custom - PersistentTokenRepository bean. -
-
- <literal>token-validity-seconds</literal> - Maps to the tokenValiditySeconds property of - AbstractRememberMeServices. Specifies the period in - seconds for which the remember-me cookie should be valid. By default it will be - valid for 14 days. -
-
- <literal>use-secure-cookie</literal> - It is recommended that remember-me cookies are only submitted over HTTPS and thus should - be flagged as secure. By default, a secure cookie will be used if the - connection over which the login request is made is secure (as it should be). - If you set this property to false, secure cookies will not be used. - Setting it to true will always set the secure flag on the cookie. - This attribute maps to the useSecureCookie property of - AbstractRememberMeServices. - -
-
- <literal>user-service-ref</literal> - The remember-me services implementations require access to a - UserDetailsService, so there has to be one - defined in the application context. If there is only one, it will be selected - and used automatically by the namespace configuration. If there are multiple - instances, you can specify a bean id explicitly using this attribute. -
-
-
-
- <literal><request-cache></literal> Element - Sets the RequestCache instance which will be used - by the ExceptionTranslationFilter to store request - information before invoking an - AuthenticationEntryPoint. -
- Parent Elements of <literal><request-cache></literal> - - http - -
-
- <literal><request-cache></literal> Attributes -
- <literal>ref</literal> - Defines a reference to a Spring bean that is a RequestCache. -
-
-
-
- <literal><session-management></literal> - Session-management related functionality is implemented by the addition of a - SessionManagementFilter to the filter stack. -
- Parent Elements of <literal><session-management></literal> - - http - -
-
- <literal><session-management></literal> Attributes -
- <literal>invalid-session-url</literal> - Setting this attribute will inject the SessionManagementFilter - with a SimpleRedirectInvalidSessionStrategy configured with - the attribute value. When an invalid session ID is submitted, the strategy will be invoked, - redirecting to the configured URL. - -
-
- <literal>session-authentication-error-url</literal> - Defines the URL of the error page which should be shown when the SessionAuthenticationStrategy - raises an exception. If not set, an unauthorized (401) error code will be returned to the client. - Note that this attribute doesn't apply if the error occurs during a form-based login, where the URL - for authentication failure will take precedence. -
-
- <literal>session-authentication-strategy-ref</literal> - Allows injection of the SessionAuthenticationStrategy instance used by the - SessionManagementFilter -
-
- <literal>session-fixation-protection</literal> - Indicates how session fixation protection will be applied when a user authenticates. If - set to "none", no protection will be applied. "newSession" will create a - new empty session, with only Spring Security-related attributes migrated. "migrateSession" will create - a new session and copy all session attributes to the new session. In Servlet 3.1 (Java EE 7) - and newer containers, specifying "changeSessionId" will keep the existing session and use the - container-supplied session fixation protection (HttpServletRequest#changeSessionId()). Defaults to - "changeSessionId" in Servlet 3.1 and newer containers, "migrateSession" in older containers. Throws an - exception if "changeSessionId" is used in older containers. - If session fixation protection is enabled, the - SessionManagementFilter is injected with an appropriately - configured DefaultSessionAuthenticationStrategy. See the - Javadoc for this class for more details. -
-
-
- Child elements of <literal><session-management></literal> - - concurrency-control - -
-
-
- <literal><concurrency-control></literal> - Adds support for concurrent session control, allowing limits to be placed on the - number of active sessions a user can have. A - ConcurrentSessionFilter will be created, and a - ConcurrentSessionControlAuthenticationStrategy will be used with the - SessionManagementFilter. If a form-login - element has been declared, the strategy object will also be injected into the - created authentication filter. An instance of - SessionRegistry (a - SessionRegistryImpl instance unless the user wishes to use a - custom bean) will be created for use by the strategy. -
- Parent Elements of <literal><concurrency-control></literal> - - session-management - -
-
- <literal><concurrency-control></literal> Attributes -
- <literal>error-if-maximum-exceeded</literal> - If set to "true" a - SessionAuthenticationException will be raised - when a user attempts to exceed the maximum allowed number of sessions. The - default behaviour is to expire the original session. -
-
- <literal>expired-url</literal> - The URL a user will be redirected to if they attempt to use a session which - has been "expired" by the concurrent session controller because the user has - exceeded the number of allowed sessions and has logged in again elsewhere. - Should be set unless exception-if-maximum-exceeded is set. If - no value is supplied, an expiry message will just be written directly back to - the response. -
-
- <literal>max-sessions</literal> - Maps to the maximumSessions property of - ConcurrentSessionControlAuthenticationStrategy. -
-
- <literal>session-registry-alias</literal> - It can also be useful to have a reference to the internal session registry - for use in your own beans or an admin interface. You can expose the internal bean - using the session-registry-alias attribute, giving it a name - that you can use elsewhere in your configuration. -
-
- <literal>session-registry-ref</literal> - The user can supply their own SessionRegistry - implementation using the session-registry-ref attribute. The - other concurrent session control beans will be wired up to use it. -
-
-
-
- <literal><x509></literal> - Adds support for X.509 authentication. An - X509AuthenticationFilter will be added to the stack and an - Http403ForbiddenEntryPoint bean will be created. The latter - will only be used if no other authentication mechanisms are in use (its only - functionality is to return an HTTP 403 error code). A - PreAuthenticatedAuthenticationProvider will also be created - which delegates the loading of user authorities to a - UserDetailsService. -
- Parent Elements of <literal><x509></literal> - - http - -
-
- <literal><x509></literal> Attributes -
- <literal>authentication-details-source-ref</literal> - A reference to an AuthenticationDetailsSource -
-
- <literal>subject-principal-regex</literal> - Defines a regular expression which will be used to extract the username from - the certificate (for use with the - UserDetailsService). -
-
- <literal>user-service-ref</literal> - Allows a specific UserDetailsService to be - used with X.509 in the case where multiple instances are configured. If not set, - an attempt will be made to locate a suitable instance automatically and use - that. -
-
-
-
- <literal><filter-chain-map></literal> - Used to explicitly configure a FilterChainProxy instance with a FilterChainMap -
- <literal><filter-chain-map></literal> Attributes -
- <literal>path-type</literal> - Superseded by the - request-matcher attribute -
-
- <literal>request-matcher</literal> - Supersedes the 'path-type' attribute. Defines the strategy use for matching incoming requests. - Currently the options are 'ant' (for ant path patterns), 'regex' for regular expressions and 'ciRegex' for - case-insensitive regular expressions. -
-
-
- Child Elements of <literal><filter-chain-map></literal> - - filter-chain - -
-
-
- <literal><filter-chain></literal> - Used within to define a specific URL pattern and the list of filters which apply to the URLs matching - that pattern. When multiple filter-chain elements are assembled in a list in order to configure a FilterChainProxy, - the most specific patterns must be placed at the top of the list, with most general ones at the bottom. -
- Parent Elements of <literal><filter-chain></literal> - - filter-chain-map - -
-
- <literal><filter-chain></literal> Attributes -
- <literal>filters</literal> - A comma separated list of references to Spring beans that implement - Filter. The value "none" means that no - Filter's should be used for this - FilterChain. -
-
- <literal>pattern</literal> - A-pattern that creates RequestMatcher in combination with the - request-matcher -
-
- <literal>request-matcher-ref</literal> - A reference to a RequestMatcher that will be used to determine if the - Filter's from the filters attribute should be invoked. -
-
-
-
- <literal><filter-invocation-definition-source></literal> - Deprecated synonym for filter-security-metadata-source -
- <literal><filter-invocation-definition-source></literal> Attributes -
- <literal>id</literal> - A bean identifier, used for referring to the bean elsewhere in the context. -
-
- <literal>lowercase-comparisons</literal> - Compare after forcing to lowercase -
-
- <literal>path-type</literal> - Superseded by - request-matcher -
-
- <literal>request-matcher</literal> - Supersedes the 'path-type' attribute. Defines the strategy use for matching incoming requests. - Currently the options are 'ant' (for ant path patterns), 'regex' for regular expressions and 'ciRegex' for - case-insensitive regular expressions. -
-
- <literal>use-expressions</literal> - Enables the use of expressions in the 'access' attributes in <intercept-url> elements - rather than the traditional list of configuration attributes. Defaults to 'false'. If - enabled, each attribute should contain a single boolean expression. If the expression evaluates to 'true', access will be - granted. -
-
-
- Child Elements of <literal><filter-invocation-definition-source></literal> - - intercept-url - -
-
-
- <literal><filter-security-metadata-source></literal> - Used to explicitly configure a FilterSecurityMetadataSource bean for use with a FilterSecurityInterceptor. Usually - only needed if you are configuring a FilterChainProxy explicitly, rather than using the - <http> element. The intercept-url elements used should only contain pattern, method and access attributes. Any - others will result in a configuration error. -
- <literal><filter-security-metadata-source></literal> Attributes -
- <literal>id</literal> - A bean identifier, used for referring to the bean elsewhere in the context. -
-
- <literal>lowercase-comparisons</literal> - Compare after forcing to lower case -
-
- <literal>path-type</literal> - Superseded by - request-matcher - -
-
- <literal>request-matcher</literal> - Supersedes the 'path-type' attribute. Defines the strategy use for matching incoming requests. - Currently the options are 'ant' (for ant path patterns), 'regex' for regular expressions and 'ciRegex' for - case-insensitive regular expressions. -
-
- <literal>use-expressions</literal> - Enables the use of expressions in the 'access' attributes in - <intercept-url> elements rather than the traditional list of configuration attributes. Defaults to 'false'. If - enabled, each attribute should contain a single boolean expression. If the expression evaluates to 'true', - access will be granted. -
-
-
- Child Elements of <literal><filter-security-metadata-source></literal> - - intercept-url - -
-
-
-
- Authentication Services - Before Spring Security 3.0, an AuthenticationManager - was automatically registered internally. Now you must register one explicitly using the - <authentication-manager> element. This creates an instance of - Spring Security's ProviderManager class, which needs to be - configured with a list of one or more - AuthenticationProvider instances. These can either be - created using syntax elements provided by the namespace, or they can be standard bean - definitions, marked for addition to the list using the - authentication-provider element. -
- <literal><authentication-manager></literal> - Every Spring Security application which uses the namespace must have include this - element somewhere. It is responsible for registering the - AuthenticationManager which provides authentication - services to the application. All elements - which create AuthenticationProvider instances should - be children of this element. -
- <literal><authentication-manager></literal> Attributes -
- <literal>alias</literal> - This attribute allows you to define an alias name for the - internal instance for use in your own configuration. Its use is described in the - namespace introduction. -
-
- <literal>erase-credentials</literal> - If set to true, the AuthenticationManger will attempt to clear any credentials data in the - returned Authentication object, once the user has been authenticated. Literally it maps to - the eraseCredentialsAfterAuthentication property of the - ProviderManager. This is discussed in the Core Services chapter. -
-
- <literal>id</literal> - This attribute allows you to define an id for the internal instance for use in your own - configuration. It is the same a the alias element, but provides a more consistent experience - with elements that use the id attribute. -
-
-
- Child Elements of <literal><authentication-manager></literal> - - authentication-provider - ldap-authentication-provider - -
-
-
- <literal><authentication-provider></literal> - Unless used with a ref attribute, this element is - shorthand for configuring a DaoAuthenticationProvider. - DaoAuthenticationProvider loads user information from a - UserDetailsService and compares the - username/password combination with the values supplied at login. The - UserDetailsService instance can be defined either - by using an available namespace element (jdbc-user-service or - by using the user-service-ref attribute to point to a bean - defined elsewhere in the application context). You can find examples of these - variations in the namespace - introduction. -
- Parent Elements of <literal><authentication-provider></literal> - - authentication-manager - -
-
- <literal><authentication-provider></literal> Attributes -
- <literal>ref</literal> - Defines a reference to a Spring bean that implements AuthenticationProvider - . - If you have written your own - AuthenticationProvider implementation (or want to - configure one of Spring Security's own implementations as a traditional bean for - some reason, then you can use the following syntax to add it to the internal - ProviderManager's list: - - - - ]]> -
-
- <literal>user-service-ref</literal> - A reference to a bean that implements UserDetailsService that may be created using the standard bean - element or the custom user-service element. -
-
-
- Child Elements of <literal><authentication-provider></literal> - - jdbc-user-service - ldap-user-service - password-encoder - user-service - -
-
-
- <literal><jdbc-user-service></literal> - Causes creation of a JDBC-based UserDetailsService. -
- <literal><jdbc-user-service></literal> Attributes -
- <literal>authorities-by-username-query</literal> - An SQL statement to query for a user's granted authorities given a username. - The default is - -
-
- <literal>cache-ref</literal> - Defines a reference to a cache for use with a UserDetailsService. -
-
- <literal>data-source-ref</literal> - The bean ID of the DataSource which provides the required tables. -
-
- <literal>group-authorities-by-username-query</literal> - An SQL statement to query user's group authorities given a username. - The default is - -
-
- <literal>id</literal> - A bean identifier, used for referring to the bean elsewhere in the context. -
-
- <literal>role-prefix</literal> - A non-empty string prefix that will be added to role strings loaded from persistent - storage (default is "ROLE_"). Use the value "none" for no prefix in cases where the default is non-empty. -
-
- <literal>users-by-username-query</literal> - An SQL statement to query a username, password, and enabled status given a username. - The default is - -
-
-
-
- <literal><password-encoder></literal> - Authentication providers can optionally be configured to use a password - encoder as described in the namespace introduction. This will result in the bean being injected - with the appropriate PasswordEncoder - instance, potentially with an accompanying - SaltSource bean to provide salt values for - hashing. -
- Parent Elements of <literal><password-encoder></literal> - - authentication-provider - password-compare - -
-
- <literal><password-encoder></literal> Attributes -
- <literal>base64</literal> - Whether a string should be base64 encoded -
-
- <literal>hash</literal> - Defines the hashing algorithm used on user passwords. We recommend strongly against using - MD4, as it is a very weak hashing algorithm. -
-
- <literal>ref</literal> - Defines a reference to a Spring bean that implements PasswordEncoder - . -
-
-
- Child Elements of <literal><password-encoder></literal> - - salt-source - -
-
-
- <literal><salt-source></literal> - Password salting strategy. A system-wide constant or a property from the UserDetails object - can be used. -
- Parent Elements of <literal><salt-source></literal> - - password-encoder - -
-
- <literal><salt-source></literal> Attributes -
- <literal>ref</literal> - Defines a reference to a Spring bean Id. -
-
- <literal>system-wide</literal> - A single value that will be used as the salt for a password encoder. -
-
- <literal>user-property</literal> - A property of the UserDetails object which will be used as salt by a password encoder. - Typically something like "username" might be used. -
-
-
-
- <literal><user-service></literal> - Creates an in-memory UserDetailsService from a properties file or a list of "user" child - elements. Usernames are converted to lower-case internally to allow for case-insensitive lookups, so - this should not be used if case-sensitivity is required. -
- <literal><user-service></literal> Attributes -
- <literal>id</literal> - A bean identifier, used for referring to the bean elsewhere in the context. -
-
- <literal>properties</literal> - The location of a Properties file where each line is in the format of - -
-
-
- Child Elements of <literal><user-service></literal> - - user - -
-
-
- <literal><user></literal> - Represents a user in the application. -
- Parent Elements of <literal><user></literal> - - user-service - -
-
- <literal><user></literal> Attributes -
- <literal>authorities</literal> - One of more authorities granted to the user. Separate authorities with a comma - (but no space). For example, "ROLE_USER,ROLE_ADMINISTRATOR" -
-
- <literal>disabled</literal> - Can be set to "true" to mark an account as disabled and unusable. -
-
- <literal>locked</literal> - Can be set to "true" to mark an account as locked and unusable. -
-
- <literal>name</literal> - The username assigned to the user. -
-
- <literal>password</literal> - The password assigned to the user. This may be hashed if the corresponding - authentication provider supports hashing (remember to set the "hash" attribute of the - "user-service" element). This attribute be omitted in the case where the data will - not be used for authentication, but only for accessing authorities. If omitted, the - namespace will generate a random value, preventing its accidental use for - authentication. Cannot be empty. -
-
-
-
-
- Method Security -
- <literal><global-method-security></literal> - This element is the primary means of adding support for securing methods on - Spring Security beans. Methods can be secured by the use of annotations (defined at - the interface or class level) or by defining a set of pointcuts as child elements, - using AspectJ syntax. -
- <literal><global-method-security></literal> Attributes -
- <literal>access-decision-manager-ref</literal> - Method security uses the same AccessDecisionManager - configuration as web security, but this can be overridden using this attribute. By default - an AffirmativeBased implementation is used for with a RoleVoter and an AuthenticatedVoter. -
-
- <literal>authentication-manager-ref</literal> - A reference to an AuthenticationManager - that should be used for method security. -
-
- <literal>jsr250-annotations</literal> - Specifies whether JSR-250 style attributes are to be used (for example "RolesAllowed"). This - will require the javax.annotation.security classes on the classpath. Setting this to true also - adds a Jsr250Voter to the - AccessDecisionManager, so you need to make sure you do this if - you are using a custom implementation and want to use these annotations. -
-
- <literal><metadata-source-ref></literal> Attribute - An external MethodSecurityMetadataSource - instance can be supplied which will take priority over other sources - (such as the default annotations). - -
-
- The <literal>mode</literal> Attribute - This attribute can be set to aspectj to specify that AspectJ - should be used instead of the default Spring AOP. Secured methods must be woven - with the AnnotationSecurityAspect from the - spring-security-aspects module. - It is important to note that AspectJ follows Java's rule that annotations on - interfaces are not inherited. This means that methods that define the Security annotaitons - on the interface will not be secured. Instead, you must place the Security annotation - on the class when using AspectJ. -
-
- <literal>order</literal> - Allows the advice "order" to be set for the method security interceptor. -
-
- <literal>pre-post-annotations</literal> - Specifies whether the use of Spring Security's pre and post invocation annotations (@PreFilter, - @PreAuthorize, @PostFilter, @PostAuthorize) should be enabled for this application context. - Defaults to "disabled". -
-
- <literal>proxy-target-class</literal> - If true, class based proxying will be used instead of interface based proxying. -
-
- <literal>run-as-manager-ref</literal> - A reference to an optional RunAsManager implementation which - will be used by the configured MethodSecurityInterceptor -
-
- <literal>secured-annotations</literal> - Specifies whether the use of Spring Security's @Secured annotations should be enabled for this - application context. Defaults to "disabled". -
-
-
- Child Elements of <literal><global-method-security></literal> - - after-invocation-provider - expression-handler - pre-post-annotation-handling - protect-pointcut - -
-
-
- <literal><after-invocation-provider></literal> - This element can be used to decorate an - AfterInvocationProvider for use by the security - interceptor maintained by the <global-method-security> - namespace. You can define zero or more of these within the - global-method-security element, each with a - ref attribute pointing to an - AfterInvocationProvider bean instance within your - application context. -
- Parent Elements of <literal><after-invocation-provider></literal> - - global-method-security - -
-
- <literal><after-invocation-provider></literal> Attributes -
- <literal>ref</literal> - Defines a reference to a Spring bean that implements - AfterInvocationProvider. -
-
-
-
- <literal><pre-post-annotation-handling></literal> - Allows the default expression-based mechanism for handling Spring Security's pre and post invocation - annotations (@PreFilter, @PreAuthorize, @PostFilter, @PostAuthorize) to be replace entirely. Only - applies if these annotations are enabled. -
- Parent Elements of <literal><pre-post-annotation-handling></literal> - - global-method-security - -
-
- Child Elements of <literal><pre-post-annotation-handling></literal> - - invocation-attribute-factory - post-invocation-advice - pre-invocation-advice - -
-
-
- <literal><invocation-attribute-factory></literal> - Defines the PrePostInvocationAttributeFactory instance which is used to generate pre and post - invocation metadata from the annotated methods. -
- Parent Elements of <literal><invocation-attribute-factory></literal> - - pre-post-annotation-handling - -
-
- <literal><invocation-attribute-factory></literal> Attributes -
- <literal>ref</literal> - Defines a reference to a Spring bean Id. -
-
-
-
- <literal><post-invocation-advice></literal> - Customizes the PostInvocationAdviceProvider with the ref as the - PostInvocationAuthorizationAdvice for the <pre-post-annotation-handling> - element. -
- Parent Elements of <literal><post-invocation-advice></literal> - - pre-post-annotation-handling - -
-
- <literal><post-invocation-advice></literal> Attributes -
- <literal>ref</literal> - Defines a reference to a Spring bean Id. -
-
-
-
- <literal><pre-invocation-advice></literal> - Customizes the PreInvocationAuthorizationAdviceVoter with the ref as the - PreInvocationAuthorizationAdviceVoter for the - <pre-post-annotation-handling> element. -
- Parent Elements of <literal><pre-invocation-advice></literal> - - pre-post-annotation-handling - -
-
- <literal><pre-invocation-advice></literal> Attributes -
- <literal>ref</literal> - Defines a reference to a Spring bean Id. -
-
-
-
- Securing Methods using <literal><protect-pointcut></literal> - Rather than defining security attributes on an individual method or class - basis using the @Secured annotation, you can define - cross-cutting security constraints across whole sets of methods and interfaces - in your service layer using the <protect-pointcut> - element. You can find an example in the namespace introduction. -
- Parent Elements of <literal><protect-pointcut></literal> - - global-method-security - -
-
- <literal><protect-pointcut></literal> Attributes -
- <literal>access</literal> - Access configuration attributes list that applies to all methods matching the pointcut, - e.g. "ROLE_A,ROLE_B" -
-
- <literal>expression</literal> - An AspectJ expression, including the 'execution' keyword. For example, 'execution(int - com.foo.TargetObject.countLength(String))' (without the quotes). -
-
-
-
- <literal><intercept-methods></literal> - Can be used inside a bean definition to add a security interceptor to the bean and set up access - configuration attributes for the bean's methods -
- <literal><intercept-methods></literal> Attributes -
- <literal>access-decision-manager-ref</literal> - Optional AccessDecisionManager bean ID to be used by the created method security interceptor. -
-
-
- Child Elements of <literal><intercept-methods></literal> - - protect - -
-
-
- <literal><method-security-metadata-source></literal> - Creates a MethodSecurityMetadataSource instance -
- <literal><method-security-metadata-source></literal> Attributes -
- <literal>id</literal> - A bean identifier, used for referring to the bean elsewhere in the context. -
-
- <literal>use-expressions</literal> - Enables the use of expressions in the 'access' attributes in - <intercept-url> elements rather than the traditional list of configuration attributes. - Defaults to 'false'. If enabled, each attribute should contain a single boolean expression. - If the expression evaluates to 'true', access will be granted. -
-
-
- Child Elements of <literal><method-security-metadata-source></literal> - - protect - -
-
-
- <literal><protect></literal> - Defines a protected method and the access control configuration attributes that apply to it. We - strongly advise you NOT to mix "protect" declarations with any services provided "global-method-security". -
- Parent Elements of <literal><protect></literal> - - intercept-methods - method-security-metadata-source - -
-
- <literal><protect></literal> Attributes -
- <literal>access</literal> - Access configuration attributes list that applies to the method, e.g. "ROLE_A,ROLE_B". -
-
- <literal>method</literal> - A method name -
-
-
-
-
- LDAP Namespace Options - LDAP is covered in some details in its own - chapter. We will expand on that here with some explanation of how the - namespace options map to Spring beans. The LDAP implementation uses Spring LDAP - extensively, so some familiarity with that project's API may be useful. -
- Defining the LDAP Server using the <literal><ldap-server></literal> - Element - This element sets up a Spring LDAP - ContextSource for use by the other LDAP beans, - defining the location of the LDAP server and other information (such as a - username and password, if it doesn't allow anonymous access) for connecting to - it. It can also be used to create an embedded server for testing. Details of the - syntax for both options are covered in the LDAP - chapter. The actual ContextSource - implementation is DefaultSpringSecurityContextSource - which extends Spring LDAP's LdapContextSource class. The - manager-dn and manager-password attributes - map to the latter's userDn and password - properties respectively. - If you only have one server defined in your application context, the other - LDAP namespace-defined beans will use it automatically. Otherwise, you can give - the element an "id" attribute and refer to it from other namespace beans using - the server-ref attribute. This is actually the bean id of the - ContextSource instance, if you want to use it in other - traditional Spring beans. -
- <literal><ldap-server></literal> Attributes -
- <literal>id</literal> - A bean identifier, used for referring to the bean elsewhere in the context. -
-
- <literal>ldif</literal> - Explicitly specifies an ldif file resource to load into an embedded LDAP server. The ldiff - is should be a Spring resource pattern (i.e. classpath:init.ldiff). The default is - classpath*:*.ldiff -
-
- <literal>manager-dn</literal> - Username (DN) of the "manager" user identity which will be used to authenticate to a - (non-embedded) LDAP server. If omitted, anonymous access will be used. -
-
- <literal>manager-password</literal> - The password for the manager DN. This is required if the manager-dn is specified. -
-
- <literal>port</literal> - Specifies an IP port number. Used to configure an embedded LDAP server, for example. The - default value is 33389. -
-
- <literal>root</literal> - Optional root suffix for the embedded LDAP server. Default is "dc=springframework,dc=org" - -
-
- <literal>url</literal> - Specifies the ldap server URL when not using the embedded LDAP server. -
-
-
-
- <literal><ldap-authentication-provider></literal> - This element is shorthand for the creation of an - LdapAuthenticationProvider instance. By default this will - be configured with a BindAuthenticator instance and a - DefaultAuthoritiesPopulator. As with all namespace - authentication providers, it must be included as a child of the - authentication-provider element. -
- Parent Elements of <literal><ldap-authentication-provider></literal> - - authentication-manager - -
-
- <literal><ldap-authentication-provider></literal> Attributes -
- <literal>group-role-attribute</literal> - The LDAP attribute name which contains the role name which will be used within Spring - Security. Maps to the DefaultLdapAuthoritiesPopulator's - groupRoleAttribute property. Defaults to "cn". -
-
- <literal>group-search-base</literal> - Search base for group membership searches. Maps to the - DefaultLdapAuthoritiesPopulator's groupSearchBase - constructor argument. Defaults to "" (searching from the root). -
-
- <literal>group-search-filter</literal> - Group search filter. Maps to the DefaultLdapAuthoritiesPopulator's - groupSearchFilter property. Defaults to (uniqueMember={0}). - The substituted parameter is the DN of the user. -
-
- <literal>role-prefix</literal> - A non-empty string prefix that will be added to role strings loaded from persistent. - Maps to the DefaultLdapAuthoritiesPopulator's - rolePrefix property. Defaults to "ROLE_". Use the value "none" for - no prefix in cases where the default is non-empty. -
-
- <literal>server-ref</literal> - The optional server to use. If omitted, and a default LDAP server is registered (using - <ldap-server> with no Id), that server will be used. -
-
- <literal>user-context-mapper-ref</literal> - Allows explicit customization of the loaded user object by specifying a - UserDetailsContextMapper bean which will be called with the context information - from the user's directory entry -
-
- <literal>user-details-class</literal> - Allows the objectClass of the user entry to be specified. If set, the framework will - attempt to load standard attributes for the defined class into the returned UserDetails - object -
-
- <literal>user-dn-pattern</literal> - If your users are at a fixed location in the directory (i.e. you can work - out the DN directly from the username without doing a directory search), you - can use this attribute to map directly to the DN. It maps directly to the - userDnPatterns property of - AbstractLdapAuthenticator. The value is a specific pattern - used to build the user's DN, for example "uid={0},ou=people". The key - "{0}" must be present and will be substituted with the username. -
-
- <literal>user-search-base</literal> - Search base for user searches. Defaults to "". Only used with a 'user-search-filter'. - If you need to perform a search to locate the user in the directory, then - you can set these attributes to control the search. The - BindAuthenticator will be configured with a - FilterBasedLdapUserSearch and the attribute values - map directly to the first two arguments of that bean's constructor. If these - attributes aren't set and no user-dn-pattern has been - supplied as an alternative, then the default search values of - user-search-filter="(uid={0})" and - user-search-base="" will be used. -
-
- <literal>user-search-filter</literal> - The LDAP filter used to search for users (optional). For example "(uid={0})". The - substituted parameter is the user's login name. - If you need to perform a search to locate the user in the directory, then - you can set these attributes to control the search. The - BindAuthenticator will be configured with a - FilterBasedLdapUserSearch and the attribute values - map directly to the first two arguments of that bean's constructor. If these - attributes aren't set and no user-dn-pattern has been - supplied as an alternative, then the default search values of - user-search-filter="(uid={0})" and - user-search-base="" will be used. -
-
-
- Child Elements of <literal><ldap-authentication-provider></literal> - - password-compare - -
-
-
- <literal><password-compare></literal> - This is used as child element to <ldap-provider> - and switches the authentication strategy from - BindAuthenticator to - PasswordComparisonAuthenticator. -
- Parent Elements of <literal><password-compare></literal> - - ldap-authentication-provider - -
-
- <literal><password-compare></literal> Attributes -
- <literal>hash</literal> - Defines the hashing algorithm used on user passwords. We recommend strongly against - using MD4, as it is a very weak hashing algorithm. -
-
- <literal>password-attribute</literal> - The attribute in the directory which contains the user password. Defaults to "userPassword". - -
-
-
- Child Elements of <literal><password-compare></literal> - - password-encoder - -
-
-
- <literal><ldap-user-service></literal> - This element configures an LDAP - UserDetailsService. The class used is - LdapUserDetailsService which is a combination of a - FilterBasedLdapUserSearch and a - DefaultLdapAuthoritiesPopulator. The attributes it supports - have the same usage as in <ldap-provider>. -
- <literal><ldap-user-service></literal> Attributes -
- <literal>cache-ref</literal> - Defines a reference to a cache for use with a UserDetailsService. -
-
- <literal>group-role-attribute</literal> - The LDAP attribute name which contains the role name which will be used within Spring - Security. Defaults to "cn". -
-
- <literal>group-search-base</literal> - Search base for group membership searches. Defaults to "" (searching from the root). -
-
- <literal>group-search-filter</literal> - Group search filter. Defaults to (uniqueMember={0}). The substituted parameter is the DN of - the user. -
-
- <literal>id</literal> - A bean identifier, used for referring to the bean elsewhere in the context. -
-
- <literal>role-prefix</literal> - A non-empty string prefix that will be added to role strings loaded from persistent - storage (e.g. "ROLE_"). Use the value "none" for no prefix in cases where the default is - non-empty. -
-
- <literal>server-ref</literal> - The optional server to use. If omitted, and a default LDAP server is registered (using - <ldap-server> with no Id), that server will be used. -
-
- <literal>user-context-mapper-ref</literal> - Allows explicit customization of the loaded user object by specifying a - UserDetailsContextMapper bean which will be called with the context information from the - user's directory entry -
-
- <literal>user-details-class</literal> - Allows the objectClass of the user entry to be specified. If set, the framework will - attempt to load standard attributes for the defined class into the returned UserDetails object - -
-
- <literal>user-search-base</literal> - Search base for user searches. Defaults to "". Only used with a 'user-search-filter'. -
-
- <literal>user-search-filter</literal> - The LDAP filter used to search for users (optional). For example "(uid={0})". The - substituted parameter is the user's login name. -
-
-
-
-
diff --git a/docs/manual/src/docbook/authorization-common.xml b/docs/manual/src/docbook/authorization-common.xml deleted file mode 100644 index e856ad8a0c..0000000000 --- a/docs/manual/src/docbook/authorization-common.xml +++ /dev/null @@ -1,345 +0,0 @@ - - - Authorization Architecture - -
- - Authorities - - As we saw in the technical overview, - all Authentication implementations store a list of - GrantedAuthority objects. These represent the authorities - that have been granted to the principal. The - GrantedAuthority objects are inserted into the - Authentication object by the - AuthenticationManager and are later read by - AccessDecisionManagers when making authorization - decisions. - GrantedAuthority is an interface with only one method: - - String getAuthority(); - This method allows - AccessDecisionManagers to obtain a precise - String representation of the - GrantedAuthority. By returning a representation as a - String, a GrantedAuthority can be - easily read by most - AccessDecisionManagers. If a - GrantedAuthority cannot be precisely represented as a - String, the GrantedAuthority is - considered complex and getAuthority() must return - null. - An example of a complex GrantedAuthority - would be an implementation that stores a list of operations and authority thresholds - that apply to different customer account numbers. Representing this complex - GrantedAuthority as a String would be - quite difficult, and as a result the getAuthority() method should - return null. This will indicate to any - AccessDecisionManager that it will need to specifically - support the GrantedAuthority implementation in order to - understand its contents. - Spring Security includes one concrete GrantedAuthority - implementation, GrantedAuthorityImpl. This allows any user-specified - String to be converted into a - GrantedAuthority. All - AuthenticationProviders included with the security architecture - use GrantedAuthorityImpl to populate the - Authentication object. -
-
- - Pre-Invocation Handling - - As we've also seen in the Technical - Overview chapter, Spring Security provides interceptors which control access to - secure objects such as method invocations or web requests. A pre-invocation decision on - whether the invocation is allowed to proceed is made by the - AccessDecisionManager. -
- The AccessDecisionManager - The AccessDecisionManager is called by the - AbstractSecurityInterceptor and is responsible for making - final access control decisions. The - AccessDecisionManager interface contains three - methods: - - void decide(Authentication authentication, Object secureObject, - Collection<ConfigAttribute> attrs) throws AccessDeniedException; - boolean supports(ConfigAttribute attribute); - boolean supports(Class clazz); - - The AccessDecisionManager's - decide method is passed all the relevant information it - needs in order to make an authorization decision. In particular, passing the secure - Object enables those arguments contained in the actual secure - object invocation to be inspected. For example, let's assume the secure object was a - MethodInvocation. It would be easy to query the - MethodInvocation for any Customer - argument, and then implement some sort of security logic in the - AccessDecisionManager to ensure the principal is - permitted to operate on that customer. Implementations are expected to throw an - AccessDeniedException if access is denied. - The supports(ConfigAttribute) method is called by the - AbstractSecurityInterceptor at startup time to determine if - the AccessDecisionManager can process the passed - ConfigAttribute. The supports(Class) method is - called by a security interceptor implementation to ensure the configured - AccessDecisionManager supports the type of secure - object that the security interceptor will present. -
-
- Voting-Based AccessDecisionManager Implementations - Whilst users can implement their own - AccessDecisionManager to control all aspects of - authorization, Spring Security includes several - AccessDecisionManager implementations that are based - on voting. illustrates the relevant - classes. -
- Voting Decision Manager - - - - - -
- Using this approach, a series of - AccessDecisionVoter implementations are polled on an - authorization decision. The AccessDecisionManager - then decides whether or not to throw an AccessDeniedException - based on its assessment of the votes. - The AccessDecisionVoter interface has three - methods: - -int vote(Authentication authentication, Object object, Collection<ConfigAttribute> attrs); -boolean supports(ConfigAttribute attribute); -boolean supports(Class clazz); - - Concrete implementations return an int, with possible values - being reflected in the AccessDecisionVoter static - fields ACCESS_ABSTAIN, ACCESS_DENIED and - ACCESS_GRANTED. A voting implementation will return - ACCESS_ABSTAIN if it has no opinion on an authorization decision. - If it does have an opinion, it must return either ACCESS_DENIED - or ACCESS_GRANTED. - There are three concrete AccessDecisionManagers - provided with Spring Security that tally the votes. The - ConsensusBased implementation will grant or deny access based on - the consensus of non-abstain votes. Properties are provided to control behavior in - the event of an equality of votes or if all votes are abstain. The - AffirmativeBased implementation will grant access if one or more - ACCESS_GRANTED votes were received (i.e. a deny vote will be - ignored, provided there was at least one grant vote). Like the - ConsensusBased implementation, there is a parameter that controls - the behavior if all voters abstain. The UnanimousBased provider - expects unanimous ACCESS_GRANTED votes in order to grant access, - ignoring abstains. It will deny access if there is any - ACCESS_DENIED vote. Like the other implementations, there is a - parameter that controls the behaviour if all voters abstain. - It is possible to implement a custom - AccessDecisionManager that tallies votes differently. - For example, votes from a particular - AccessDecisionVoter might receive additional - weighting, whilst a deny vote from a particular voter may have a veto effect. -
- <classname>RoleVoter</classname> - The most commonly used AccessDecisionVoter - provided with Spring Security is the simple RoleVoter, - which treats configuration attributes as simple role names and votes to grant - access if the user has been assigned that role. - It will vote if any ConfigAttribute begins with - the prefix ROLE_. It will vote to grant access if there is a - GrantedAuthority which returns a - String representation (via the - getAuthority() method) exactly equal to one or more - ConfigAttributes starting with the prefix - ROLE_. If there is no exact match of any - ConfigAttribute starting with ROLE_, the - RoleVoter will vote to deny access. If no - ConfigAttribute begins with ROLE_, the - voter will abstain. -
-
- <classname>AuthenticatedVoter</classname> - Another voter which we've implicitly seen is the - AuthenticatedVoter, which can be used to differentiate - between anonymous, fully-authenticated and remember-me authenticated users. Many - sites allow certain limited access under remember-me authentication, but require - a user to confirm their identity by logging in for full access. - When we've used the attribute IS_AUTHENTICATED_ANONYMOUSLY - to grant anonymous access, this attribute was being processed by the - AuthenticatedVoter. See the Javadoc for this class for - more information. -
-
- Custom Voters - Obviously, you can also implement a custom - AccessDecisionVoter and you can - put just about any access-control logic you want in it. It might - be specific to your application (business-logic related) or it - might implement some security administration logic. For example, you'll find - a - blog article on the SpringSource web site which describes how to - use a voter to deny access in real-time to users whose accounts have - been suspended. - -
-
-
-
- - After Invocation Handling - - Whilst the AccessDecisionManager is called by the - AbstractSecurityInterceptor before proceeding with the secure - object invocation, some applications need a way of modifying the object actually - returned by the secure object invocation. Whilst you could easily implement your own AOP - concern to achieve this, Spring Security provides a convenient hook that has several - concrete implementations that integrate with its ACL capabilities. - illustrates Spring Security's - AfterInvocationManager and its concrete implementations.
- After Invocation Implementation - - - - - -
- Like many other parts of Spring Security, AfterInvocationManager - has a single concrete implementation, AfterInvocationProviderManager, - which polls a list of AfterInvocationProviders. Each - AfterInvocationProvider is allowed to modify the return object or - throw an AccessDeniedException. Indeed multiple providers can modify - the object, as the result of the previous provider is passed to the next in the - list. - Please be aware that if you're using AfterInvocationManager, you - will still need configuration attributes that allow the - MethodSecurityInterceptor's - AccessDecisionManager to allow an operation. If you're - using the typical Spring Security included - AccessDecisionManager implementations, having no - configuration attributes defined for a particular secure method invocation will cause - each AccessDecisionVoter to abstain from voting. In turn, - if the AccessDecisionManager property - "allowIfAllAbstainDecisions" is false, an - AccessDeniedException will be thrown. You may avoid this potential - issue by either (i) setting "allowIfAllAbstainDecisions" to - true (although this is generally not recommended) or (ii) simply - ensure that there is at least one configuration attribute that an - AccessDecisionVoter will vote to grant access for. This - latter (recommended) approach is usually achieved through a ROLE_USER - or ROLE_AUTHENTICATED configuration attribute. - - -
-
- Hierarchical Roles - - It is a common requirement that a particular role in an application should automatically - include other roles. For example, in an application which has the concept of - an admin and a user role, you may want an admin to be able to - do everything a normal user can. To achieve this, you can either make sure that all admin users - are also assigned the user role. Alternatively, you can modify every access constraint - which requires the user role to also include the admin role. - This can get quite complicated if you have a lot of different roles in your application. - - - The use of a role-hierarchy allows you to configure which roles (or authorities) should include others. - An extended version of Spring Security's RoleVoter, - RoleHierarchyVoter, is configured with a RoleHierarchy, - from which it obtains all the reachable authorities which the user is assigned. - A typical configuration might look like this: - - - - - - - ROLE_ADMIN > ROLE_STAFF - ROLE_STAFF > ROLE_USER - ROLE_USER > ROLE_GUEST - - -]]> - - Here we have four roles in a hierarchy ROLE_ADMIN => ROLE_STAFF => ROLE_USER => ROLE_GUEST. - A user who is authenticated with ROLE_ADMIN, will behave as if they have all four roles when - security contraints are evaluated against an AccessDecisionManager cconfigured - with the above RoleHierarchyVoter. The > symbol can be thought of - as meaning includes. - - - Role hierarchies offer a convenient means of simplifying the access-control configuration data for your - application and/or reducing the number of authorities which you need to assign to a user. For more - complex requirements you may wish to define a logical mapping between the specific access-rights your - application requires and the roles that are assigned to users, translating between the two when loading - the user information. - - -
- -
diff --git a/docs/manual/src/docbook/basic-and-digest-auth.xml b/docs/manual/src/docbook/basic-and-digest-auth.xml deleted file mode 100644 index 0bf9b5633b..0000000000 --- a/docs/manual/src/docbook/basic-and-digest-auth.xml +++ /dev/null @@ -1,169 +0,0 @@ - - - Basic and Digest Authentication - - Basic and digest authentiation are alternative authentication mechanisms which are popular - in web applications. Basic authentication is often used with stateless clients which pass - their credentials on each request. It's quite common to use it in combination with - form-based authentication where an application is used through both a browser-based user - interface and as a web-service. However, basic authentication transmits the password as - plain text so it should only really be used over an encrypted transport layer such as - HTTPS. -
- - <classname>BasicAuthenticationFilter</classname> - - BasicAuthenticationFilter is responsible for processing basic - authentication credentials presented in HTTP headers. This can be used for - authenticating calls made by Spring remoting protocols (such as Hessian and Burlap), as - well as normal browser user agents (such as Firefox and Internet Explorer). The standard - governing HTTP Basic Authentication is defined by RFC 1945, Section 11, and - BasicAuthenticationFilter conforms with this RFC. Basic - Authentication is an attractive approach to authentication, because it is very widely - deployed in user agents and implementation is extremely simple (it's just a Base64 - encoding of the username:password, specified in an HTTP header). -
- - Configuration - - To implement HTTP Basic Authentication, you need to add a - BasicAuthenticationFilter to your filter chain. The application - context should contain BasicAuthenticationFilter and its required - collaborator: - - - - - - - -]]> - - The configured AuthenticationManager processes each - authentication request. If authentication fails, the configured - AuthenticationEntryPoint will be used to retry the - authentication process. Usually you will use the filter in combination with a - BasicAuthenticationEntryPoint, which returns a 401 response with - a suitable header to retry HTTP Basic authentication. If authentication is - successful, the resulting Authentication object will - be placed into the SecurityContextHolder as usual. - If the authentication event was successful, or authentication was not attempted - because the HTTP header did not contain a supported authentication request, the - filter chain will continue as normal. The only time the filter chain will be - interrupted is if authentication fails and the - AuthenticationEntryPoint is called. -
-
-
- <classname>DigestAuthenticationFilter</classname> - DigestAuthenticationFilter is capable of processing digest - authentication credentials presented in HTTP headers. Digest Authentication attempts to - solve many of the weaknesses of Basic authentication, specifically by ensuring - credentials are never sent in clear text across the wire. Many user agents support - Digest Authentication, including FireFox and Internet Explorer. The standard governing - HTTP Digest Authentication is defined by RFC 2617, which updates an earlier version of - the Digest Authentication standard prescribed by RFC 2069. Most user agents implement - RFC 2617. Spring Security's DigestAuthenticationFilter is - compatible with the "auth" quality of protection - (qop) prescribed by RFC 2617, which also provides backward - compatibility with RFC 2069. Digest Authentication is a more attractive option if you - need to use unencrypted HTTP (i.e. no TLS/HTTPS) and wish to maximise security of the - authentication process. Indeed Digest Authentication is a mandatory requirement for the - WebDAV protocol, as noted by RFC 2518 Section 17.1. - Digest Authentication is definitely the most secure choice between Form - Authentication, Basic Authentication and Digest Authentication, although extra security - also means more complex user agent implementations. Central to Digest Authentication is - a "nonce". This is a value the server generates. Spring Security's nonce adopts the - following format: - - - base64(expirationTime + ":" + md5Hex(expirationTime + ":" + key)) - - expirationTime: The date and time when the nonce expires, expressed in milliseconds - key: A private key to prevent modification of the nonce token - - The DigestAuthenticatonEntryPoint has a property specifying the - key used for generating the nonce tokens, along with a - nonceValiditySeconds property for determining the expiration time - (default 300, which equals five minutes). Whist ever the nonce is valid, the digest is - computed by concatenating various strings including the username, password, nonce, URI - being requested, a client-generated nonce (merely a random value which the user agent - generates each request), the realm name etc, then performing an MD5 hash. Both the - server and user agent perform this digest computation, resulting in different hash codes - if they disagree on an included value (eg password). In Spring Security implementation, - if the server-generated nonce has merely expired (but the digest was otherwise valid), - the DigestAuthenticationEntryPoint will send a - "stale=true" header. This tells the user agent there is no need to - disturb the user (as the password and username etc is correct), but simply to try again - using a new nonce. - An appropriate value for DigestAuthenticationEntryPoint's - nonceValiditySeconds parameter will depend on your application. - Extremely secure applications should note that an intercepted authentication header can - be used to impersonate the principal until the expirationTime - contained in the nonce is reached. This is the key principle when selecting an - appropriate setting, but it would be unusual for immensely secure applications to not be - running over TLS/HTTPS in the first instance. - Because of the more complex implementation of Digest Authentication, there are often - user agent issues. For example, Internet Explorer fails to present an - "opaque" token on subsequent requests in the same session. Spring - Security filters therefore encapsulate all state information into the - "nonce" token instead. In our testing, Spring Security's - implementation works reliably with FireFox and Internet Explorer, correctly handling - nonce timeouts etc. -
- Configuration - Now that we've reviewed the theory, let's see how to use it. To implement HTTP - Digest Authentication, it is necessary to define - DigestAuthenticationFilter in the filter chain. The application - context will need to define the DigestAuthenticationFilter and - its required collaborators: - - - - - - - - - - -]]> - - The configured UserDetailsService is needed because - DigestAuthenticationFilter must have direct access to the clear - text password of a user. Digest Authentication will NOT work if you are using - encoded passwords in your DAO It is possible to encode the password in the - format HEX( MD5(username:realm:password) ) provided the - DigestAuthenticationFilter.passwordAlreadyEncoded is set to true. - However, other password encodings will not work with digest authentication.. - The DAO collaborator, along with the UserCache, are typically shared directly - with a DaoAuthenticationProvider. The - authenticationEntryPoint property must be - DigestAuthenticationEntryPoint, so that - DigestAuthenticationFilter can obtain the correct - realmName and key for digest - calculations. - Like BasicAuthenticationFilter, if authentication is successful - an Authentication request token will be placed into - the SecurityContextHolder. If the authentication event was - successful, or authentication was not attempted because the HTTP header did not - contain a Digest Authentication request, the filter chain will continue as normal. - The only time the filter chain will be interrupted is if authentication fails and - the AuthenticationEntryPoint is called, as discussed - in the previous paragraph. - Digest Authentication's RFC offers a range of additional features to further - increase security. For example, the nonce can be changed on every request. Despite - this, Spring Security implementation was designed to minimise the complexity of the - implementation (and the doubtless user agent incompatibilities that would emerge), - and avoid needing to store server-side state. You are invited to review RFC 2617 if - you wish to explore these features in more detail. As far as we are aware, Spring - Security's implementation does comply with the minimum standards of this RFC. -
-
-
diff --git a/docs/manual/src/docbook/cas-auth-provider.xml b/docs/manual/src/docbook/cas-auth-provider.xml deleted file mode 100644 index a9d504775d..0000000000 --- a/docs/manual/src/docbook/cas-auth-provider.xml +++ /dev/null @@ -1,567 +0,0 @@ - - CAS Authentication -
- Overview - JA-SIG produces an enterprise-wide single sign on system known as CAS. Unlike other - initiatives, JA-SIG's Central Authentication Service is open source, widely used, simple - to understand, platform independent, and supports proxy capabilities. Spring Security - fully supports CAS, and provides an easy migration path from single-application - deployments of Spring Security through to multiple-application deployments secured by an - enterprise-wide CAS server. - You can learn more about CAS at http://www.ja-sig.org/cas. You will - also need to visit this site to download the CAS Server files. -
-
- - How CAS Works - - Whilst the CAS web site contains documents that detail the architecture of CAS, we - present the general overview again here within the context of Spring Security. Spring Security - 3.x supports CAS 3. At the time of writing, the CAS server was at version 3.4. - Somewhere in your enterprise you will need to setup a CAS server. The CAS server is - simply a standard WAR file, so there isn't anything difficult about setting up your - server. Inside the WAR file you will customise the login and other single sign on pages - displayed to users. - When deploying a CAS 3.4 server, you will also need to specify an - AuthenticationHandler in the - deployerConfigContext.xml included with CAS. The - AuthenticationHandler has a simple method that returns a boolean as to - whether a given set of Credentials is valid. Your AuthenticationHandler - implementation will need to link into some type of backend authentication repository, such as - an LDAP server or database. CAS itself includes numerous - AuthenticationHandlers out of the box to assist with this. When you - download and deploy the server war file, it is set up to successfully authenticate users who - enter a password matching their username, which is useful for testing. - Apart from the CAS server itself, the other key players are of course the secure web - applications deployed throughout your enterprise. These web applications are known as - "services". There are three types of services. Those that authenticate service tickets, those that - can obtain proxy tickets, and those that authenticate proxy tickets. Authenticating a proxy ticket - differs because the list of proxies must be validated and often times a proxy ticket can be reused. - -
- Spring Security and CAS Interaction Sequence - - The basic interaction between a web browser, CAS server and a - Spring Security-secured service is as follows: - - - - The web user is browsing the service's public pages. CAS or - Spring Security is not involved. - - - - The user eventually requests a page that is either secure or - one of the beans it uses is secure. Spring Security's - ExceptionTranslationFilter will detect the - AccessDeniedException or AuthenticationException. - - - - Because the user's Authentication object (or lack - thereof) caused an AuthenticationException, the - ExceptionTranslationFilter will call the configured - AuthenticationEntryPoint. If using CAS, this will be - the CasAuthenticationEntryPoint class. - - - - The CasAuthenticationEntryPoint will redirect the user's browser - to the CAS server. It will also indicate a service parameter, which - is the callback URL for the Spring Security service (your application). For example, the - URL to which the browser is redirected might be - https://my.company.com/cas/login?service=https%3A%2F%2Fserver3.company.com%2Fwebapp%2Fj_spring_cas_security_check. - - - - After the user's browser redirects to CAS, they will be - prompted for their username and password. If the user presents a - session cookie which indicates they've previously logged on, they - will not be prompted to login again (there is an exception to this - procedure, which we'll cover later). CAS will use the - PasswordHandler (or - AuthenticationHandler if using CAS 3.0) - discussed above to decide whether the username and password is - valid. - - - - Upon successful login, CAS will redirect the user's browser - back to the original service. It will also include a - ticket parameter, which is an opaque string - representing the "service ticket". Continuing our earlier example, - the URL the browser is redirected to might be - https://server3.company.com/webapp/j_spring_cas_security_check?ticket=ST-0-ER94xMJmn6pha35CQRoZ. - - - - Back in the service web application, the CasAuthenticationFilter is - always listening for requests to /j_spring_cas_security_check (this - is configurable, but we'll use the defaults in this introduction). The processing filter - will construct a UsernamePasswordAuthenticationToken representing the - service ticket. The principal will be equal to - CasAuthenticationFilter.CAS_STATEFUL_IDENTIFIER, whilst the credentials - will be the service ticket opaque value. This authentication request will then be handed - to the configured AuthenticationManager. - - - - The AuthenticationManager implementation - will be the ProviderManager, which is in turn - configured with the CasAuthenticationProvider. - The CasAuthenticationProvider only responds to - UsernamePasswordAuthenticationTokens containing - the CAS-specific principal (such as - CasAuthenticationFilter.CAS_STATEFUL_IDENTIFIER) - and CasAuthenticationTokens (discussed - later). - - - - CasAuthenticationProvider will validate the service ticket using a - TicketValidator implementation. This will typically be a - Cas20ServiceTicketValidator which is one of the classes - included in the CAS client library. In the event the application needs to validate proxy tickets, the - Cas20ProxyTicketValidator is used. The - TicketValidator makes an HTTPS request to the CAS server in order to - validate the service ticket. It may also include a proxy callback URL, which is included in this example: - https://my.company.com/cas/proxyValidate?service=https%3A%2F%2Fserver3.company.com%2Fwebapp%2Fj_spring_cas_security_check&ticket=ST-0-ER94xMJmn6pha35CQRoZ&pgtUrl=https://server3.company.com/webapp/j_spring_cas_security_proxyreceptor. - - - - - Back on the CAS server, the validation request will be - received. If the presented service ticket matches the service URL - the ticket was issued to, CAS will provide an affirmative response - in XML indicating the username. If any proxy was involved in the - authentication (discussed below), the list of proxies is also - included in the XML response. - - - - [OPTIONAL] If the request to the CAS validation service included the proxy callback - URL (in the pgtUrl parameter), CAS will include a - pgtIou string in the XML response. This pgtIou - represents a proxy-granting ticket IOU. The CAS server will then create its own HTTPS - connection back to the pgtUrl. This is to mutually authenticate the - CAS server and the claimed service URL. The HTTPS connection will be used to send a - proxy granting ticket to the original web application. For example, - https://server3.company.com/webapp/j_spring_cas_security_proxyreceptor?pgtIou=PGTIOU-0-R0zlgrl4pdAQwBvJWO3vnNpevwqStbSGcq3vKB2SqSFFRnjPHt&pgtId=PGT-1-si9YkkHLrtACBo64rmsi3v2nf7cpCResXg5MpESZFArbaZiOKH. - - - - The Cas20TicketValidator will parse the XML received from the - CAS server. It will return to the CasAuthenticationProvider a - TicketResponse, which includes the username (mandatory), proxy list - (if any were involved), and proxy-granting ticket IOU (if the proxy callback was - requested). - - - - Next CasAuthenticationProvider will call - a configured CasProxyDecider. The - CasProxyDecider indicates whether the proxy - list in the TicketResponse is acceptable to the - service. Several implementations are provided with Spring - Security: RejectProxyTickets, - AcceptAnyCasProxy and - NamedCasProxyDecider. These names are largely - self-explanatory, except NamedCasProxyDecider - which allows a List of trusted proxies to be - provided. - - - - CasAuthenticationProvider will next - request a AuthenticationUserDetailsService to load the - GrantedAuthority objects that apply to the user - contained in the Assertion. - - - - If there were no problems, - CasAuthenticationProvider constructs a - CasAuthenticationToken including the details - contained in the TicketResponse and the - GrantedAuthoritys. - - - - Control then returns to - CasAuthenticationFilter, which places the created - CasAuthenticationToken in the security context. - - - - The user's browser is redirected to the original page that - caused the AuthenticationException (or a - custom destination depending on - the configuration). - - - - It's good that you're still here! Let's now look at how this is configured -
- -
-
- - Configuration of CAS Client - - The web application side of CAS is made easy due to Spring Security. It is assumed you - already know the basics of using Spring Security, so these are not covered again below. - We'll assume a namespace based configuration is being used and add in the CAS beans as - required. Each section builds upon the previous section. A full - CAS sample application can be found in the Spring - Security Samples. -
- - Service Ticket Authentication - - This section describes how to setup Spring Security to authenticate Service Tickets. Often times - this is all a web application requires. You will need to add a ServiceProperties - bean to your application context. This represents your CAS service: - - - - ]]> - - The service must equal a URL that will be monitored by the - CasAuthenticationFilter. The sendRenew defaults to - false, but should be set to true if your application is particularly sensitive. What - this parameter does is tell the CAS login service that a single sign on login is - unacceptable. Instead, the user will need to re-enter their username and password in - order to gain access to the service. - The following beans should be configured to commence the CAS authentication process - (assuming you're using a namespace configuration): - - ... - - - - - - - - - - - -]]> - - For CAS to operate, the ExceptionTranslationFilter must have - its authenticationEntryPoint property set to the - CasAuthenticationEntryPoint bean. This can easily be done using - entry-point-ref as is - done in the example above. The CasAuthenticationEntryPoint must refer to the - ServiceProperties bean (discussed above), which provides the URL - to the enterprise's CAS login server. This is where the user's browser will be - redirected. - The CasAuthenticationFilter has very similar properties to the - UsernamePasswordAuthenticationFilter (used for form-based - logins). You can use these properties to customize things like behavior for authentication - success and failure. - Next you need to add a CasAuthenticationProvider and its - collaborators: - - - - - - - - - - - - - - - - - - - - - ... - ]]> - The CasAuthenticationProvider uses a - UserDetailsService instance to load the authorities for a - user, once they have been authenticated by CAS. We've shown a simple in-memory setup - here. Note that the CasAuthenticationProvider does not actually use - the password for authentication, but it does use the authorities. - The beans are all reasonably self-explanatory if you refer back to the - How CAS Works section. - This completes the most basic configuration for CAS. If you haven't made any - mistakes, your web application should happily work within the - framework of CAS single sign on. No other parts of Spring Security - need to be concerned about the fact CAS handled authentication. In the following sections - we will discuss some (optional) more advanced configurations. -
-
- - Single Logout - - The CAS protocol supports Single Logout and can be easily added to your Spring - Security configuration. Below are updates to the Spring Security configuration - that handle Single Logout - ... - - - - - - - - - - - - - - - - ]]> The logout element logs the user out of the local application, but - does not terminate the session with the CAS server or any other applications that have been logged - into. The requestSingleLogoutFilter filter will allow the url of - /spring_security_cas_logout to be requested to redirect the application to the - configured CAS Server logout url. Then the CAS Server will send a Single Logout request to all the - services that were signed into. The singleLogoutFilter handles the Single Logout - request by looking up the HttpSession in a static Map - and then invalidating it. - It might be confusing why both the logout element and the - singleLogoutFilter are needed. It is considered best practice to logout locally - first since the SingleSignOutFilter just stores the - HttpSession in a static Map in order to - call invalidate on it. With the configuration above, the flow of logout would be: - - The user requests /j_spring_security_logout which would log the user - out of the local application and send the user to the logout success page. - The logout success page, /cas-logout.jsp, should instruct the user - to click a link pointing to /j_spring_cas_security_logout in order to logout - out of all applications. - When the user clicks the link, the user is redirected to the CAS single logout URL - (https://localhost:9443/cas/logout). - On the CAS Server side, the CAS single logout URL then submits single logout requests to - all the CAS Services. On the CAS Service side, JASIG's - SingleSignOutFilter processes the logout request by invaliditing the - original session. - - - The next step is to add the following to your web.xml - - characterEncodingFilter - org.springframework.web.filter.CharacterEncodingFilter - - encoding - UTF-8 - - - - characterEncodingFilter - /* - - - org.jasig.cas.client.session.SingleSignOutHttpSessionListener - ]]> - When using the SingleSignOutFilter you might encounter some encoding issues. Therefore it is - recommended to add the CharacterEncodingFilter to ensure that the character - encoding is correct when using the SingleSignOutFilter. Again, refer to JASIG's - documentation for details. The SingleSignOutHttpSessionListener ensures that - when an HttpSession expires, the mapping used for single logout is - removed. -
-
- - Authenticating to a Stateless Service with CAS - - This section describes how to authenticate to a service using CAS. In other words, - this section discusses how to setup a client that uses a service that authenticates with - CAS. The next section describes how to setup a stateless service to Authenticate - using CAS. -
- - Configuring CAS to Obtain Proxy Granting Tickets - - In order to authenticate to a stateless service, the application needs to obtain a proxy granting ticket - (PGT). This section describes how to configure Spring Security to obtain a PGT building upon then - Service Ticket Authentication configuration. - The first step is to include a ProxyGrantingTicketStorage in your Spring Security - configuration. This is used to store PGT's that are obtained by the - CasAuthenticationFilter so that they can be used to obtain proxy tickets. An example - configuration is shown below - -]]> - The next step is to update the CasAuthenticationProvider to be able to obtain proxy - tickets. To do this replace the Cas20ServiceTicketValidator with a - Cas20ProxyTicketValidator. The proxyCallbackUrl should be set to - a URL that the application will receive PGT's at. Last, the configuration should also reference the - ProxyGrantingTicketStorage so it can use a PGT to obtain proxy tickets. - You can find an example of the configuration changes that should be made below. - - ... - - - - - - - - - -]]> - The last step is to update the CasAuthenticationFilter to accept PGT and to store them - in the ProxyGrantingTicketStorage. It is important the the proxyReceptorUrl - matches the proxyCallbackUrl of the Cas20ProxyTicketValidator. An example - configuration is shown below. - - ... - - - -]]> -
-
- - Calling a Stateless Service Using a Proxy Ticket - - Now that Spring Security obtains PGTs, you can use them to create proxy tickets which can be used to authenticate - to a stateless service. The CAS sample application contains a working example in - the ProxyTicketSampleServlet. Example code can be found below: - -
-
-
- - Proxy Ticket Authentication - - The CasAuthenticationProvider distinguishes - between stateful and stateless clients. A stateful client is - considered any that submits to the filterProcessUrl of the - CasAuthenticationFilter. A stateless client is any that - presents an authentication request to CasAuthenticationFilter - on a URL other than the filterProcessUrl. - Because remoting protocols have no way of presenting themselves - within the context of an HttpSession, it isn't - possible to rely on the default practice of storing the security context in the - session between requests. Furthermore, because the CAS server invalidates a - ticket after it has been validated by the TicketValidator, - presenting the same proxy ticket on subsequent requests will not - work. - One obvious option is to not use CAS at all for remoting - protocol clients. However, this would eliminate many of the desirable - features of CAS. As a middle-ground, the - CasAuthenticationProvider uses a - StatelessTicketCache. This is used solely for stateless clients - which use a principal equal to - CasAuthenticationFilter.CAS_STATELESS_IDENTIFIER. What - happens is the CasAuthenticationProvider will store - the resulting CasAuthenticationToken in the - StatelessTicketCache, keyed on the proxy ticket. - Accordingly, remoting protocol clients can present the same proxy - ticket and the CasAuthenticationProvider will not - need to contact the CAS server for validation (aside from the first - request). Once authenticated, the proxy ticket could be used for URLs other than the - original target service. - This section builds upon the previous sections to accomodate proxy ticket authentication. - The first step is to specify to authenticate all artifacts as shown below. - - ... - - -]]> - The next step is to specify serviceProperties and the - authenticationDetailsSource for the CasAuthenticationFilter. - The serviceProperties property instructs the - CasAuthenticationFilter to attempt to authenticate all artifacts instead of only - ones present on the filterProcessUrl. The - ServiceAuthenticationDetailsSource creates a - ServiceAuthenticationDetails that ensures the current URL, based - upon the HttpServletRequest, is used as the service URL when validating the ticket. - The method for generating the service URL can be customized by injecting a custom - AuthenticationDetailsSource that returns a custom - ServiceAuthenticationDetails. - ... - - - - - -]]> - You will also need to update the CasAuthenticationProvider to handle proxy tickets. - To do this replace the Cas20ServiceTicketValidator with a - Cas20ProxyTicketValidator. You will need to configure the - statelessTicketCache and which proxies you want to accept. You can find an example of the updates - required to accept all proxies below. - - ... - - - - - - - - - - - - - - - - - - - - - -]]> -
-
-
diff --git a/docs/manual/src/docbook/channel-security.xml b/docs/manual/src/docbook/channel-security.xml deleted file mode 100644 index 3d609fcfd0..0000000000 --- a/docs/manual/src/docbook/channel-security.xml +++ /dev/null @@ -1,140 +0,0 @@ - - - Channel Security - -
- - Overview - - In addition to coordinating the authentication and authorization requirements of your - application, Spring Security is also able to ensure unauthenticated web requests have - certain properties. These properties may include being of a particular transport type, - having a particular HttpSession attribute set and so on. The most - common requirement is for your web requests to be received using a particular transport - protocol, such as HTTPS. - An important issue in considering transport security is that of session hijacking. - Your web container manages a HttpSession by reference to a - jsessionid that is sent to user agents either via a cookie or URL - rewriting. If the jsessionid is ever sent over HTTP, there is a - possibility that session identifier can be intercepted and used to impersonate the user - after they complete the authentication process. This is because most web containers - maintain the same session identifier for a given user, even after they switch from HTTP - to HTTPS pages. - If session hijacking is considered too significant a risk for your particular - application, the only option is to use HTTPS for every request. This means the - jsessionid is never sent across an insecure channel. You will need to - ensure your web.xml-defined <welcome-file> - points to an HTTPS location, and the application never directs the user to an HTTP - location. Spring Security provides a solution to assist with the latter. -
-
- - Configuration - - Channel security is supported by the security - namespace by means of the requires-channel attribute on the - <intercept-url> element and this is the simplest (and - recommended approach). - To configure channel security explicitly, you would define the following the filter in - your application context: - - - - - - - - - - - - - - - - - - - - - -]]> - - Like FilterSecurityInterceptor, Apache Ant style paths are also - supported by the ChannelProcessingFilter. - The ChannelProcessingFilter operates by filtering all web requests - and determining the configuration attributes that apply. It then delegates to the - ChannelDecisionManager. The default implementation, - ChannelDecisionManagerImpl, should suffice in most cases. It simply - delegates to the list of configured ChannelProcessor instances. The - attribute ANY_CHANNEL can be used to override this behaviour and skip - a particular URL. Otherwise, a ChannelProcessor will review the - request, and if it is unhappy with the request (e.g. if it was received across the - incorrect transport protocol), it will perform a redirect, throw an exception or take - whatever other action is appropriate. - Included with Spring Security are two concrete ChannelProcessor - implementations: SecureChannelProcessor ensures requests with a - configuration attribute of REQUIRES_SECURE_CHANNEL are received over - HTTPS, whilst InsecureChannelProcessor ensures requests with a - configuration attribute of REQUIRES_INSECURE_CHANNEL are received - over HTTP. Both implementations delegate to a ChannelEntryPoint if - the required transport protocol is not used. The two - ChannelEntryPoint implementations included with Spring Security - simply redirect the request to HTTP and HTTPS as appropriate. Appropriate defaults are - assigned to the ChannelProcessor implementations for the - configuration attribute keywords they respond to and the - ChannelEntryPoint they delegate to, although you have the - ability to override these using the application context. - Note that the redirections are absolute (eg - http://www.company.com:8080/app/page), not relative (eg - /app/page). During testing it was discovered that Internet Explorer 6 - Service Pack 1 has a bug whereby it does not respond correctly to a redirection - instruction which also changes the port to use. Accordingly, absolute URLs are used in - conjunction with bug detection logic in the PortResolverImpl that - is wired up by default to many Spring Security beans. Please refer to the JavaDocs for - PortResolverImpl for further details. - You should note that using a secure channel is recommended if usernames and passwords - are to be kept secure during the login process. If you do decide to use - ChannelProcessingFilter with form-based login, please ensure that - your login page is set to REQUIRES_SECURE_CHANNEL, and that the - LoginUrlAuthenticationEntryPoint.forceHttps property is - true. -
-
- - Conclusion - - Once configured, using the channel security filter is very easy. Simply request pages - without regard to the protocol (ie HTTP or HTTPS) or port (eg 80, 8080, 443, 8443 etc). - Obviously you'll still need a way of making the initial request (probably via the - web.xml <welcome-file> or a well-known home - page URL), but once this is done the filter will perform redirects as defined by your - application context. - You can also add your own ChannelProcessor implementations to the - ChannelDecisionManagerImpl. For example, you might set a - HttpSession attribute when a human user is detected via a "enter the - contents of this graphic" procedure. Your ChannelProcessor would - respond to say REQUIRES_HUMAN_USER configuration attributes and - redirect to an appropriate entry point to start the human user validation process if the - HttpSession attribute is not currently set. - To decide whether a security check belongs in a ChannelProcessor or - an AccessDecisionVoter, remember that the former is - designed to handle unauthenticated requests, whilst the latter is designed to handle - authenticated requests. The latter therefore has access to the granted authorities of - the authenticated principal. In addition, problems detected by a - ChannelProcessor will generally cause an HTTP/HTTPS redirection so - its requirements can be met, whilst problems detected by an - AccessDecisionVoter will ultimately result in an - AccessDeniedException (depending on the governing - AccessDecisionManager). -
-
diff --git a/docs/manual/src/docbook/class-index-html.xsl b/docs/manual/src/docbook/class-index-html.xsl deleted file mode 100644 index d8ccc27c7f..0000000000 --- a/docs/manual/src/docbook/class-index-html.xsl +++ /dev/null @@ -1,43 +0,0 @@ - - - - - http://static.springsource.org/spring-security/site/docs/3.0.x/apidocs/ - http://static.springsource.org/spring-security/site/docs/3.0.x/reference/ - - - - - Spring Security Class and Interface Index - - -

Class and Interface Index

-

An list of classes and interfaces used in Spring Security with links to the sections in the Spring Security manual which - refer to them.

-
- -
- - -
- - -
- - -

-
- -

-
-
- - - - - -
-
-
- -
diff --git a/docs/manual/src/docbook/classindex.pl b/docs/manual/src/docbook/classindex.pl deleted file mode 100755 index 9690681497..0000000000 --- a/docs/manual/src/docbook/classindex.pl +++ /dev/null @@ -1,127 +0,0 @@ -#! /usr/bin/perl - -# Intended to generate an index of classnames to references in the manual (using the interfacename and classname elements). -# -# Builds an index of classnames to Javadoc (or src xref) links, from the allclasses-frame.html file. -# Processes the ref manual docbook files, building an index of classname to section ids where the class is referenced -# -# - -use strict; - -# Get list of links to class src packages from Javadoc -#system("curl http://static.springsource.org/spring-security/site/docs/3.0.x/apidocs/allclasses-frame.html > allclasses-frame.html"); -# Manual front page gives us section numbers -#system("curl http://static.springsource.org/spring-security/site/docs/3.0.x/reference/springsecurity.html > springsecurity.html"); - -my $index_page = `cat springsecurity.html`; - -my @all_classes = `cat allclasses-frame.html`; - -$#all_classes > 0 || die "No lines in Javadoc"; - -# Src XREF format -#AbstractAccessDecisionManager -# Javadoc format -#AbstractAclProvider - -my %classnames_to_src; - -print "Extracting classnames to links map from Javadoc...\n"; - -while ($_ = pop @all_classes) { - chomp; -# Get rid of the italic tags round interface names - $_ =~ s///; - $_ =~ s/<\/I>//; - next unless $_ =~ /(([a-zA-Z0-9_]+?))<\/A>.*/; -# print "Adding class $1, $2\n"; - $classnames_to_src{$2} = $1; -} - -#my @docbook = glob("*.xml"); -# The list of docbook files xincluded in the manual -my @docbook; - -print "Building list of docbook source files...\n"; - -# Read the includes rather than using globbing to get the ordering right for the index. -open MAINDOC, ") { - if (/href="(.*\.xml)"/) { - push @docbook, $1; - } -} - -# Hash of xml:id (i.e. anchor) to filename.html#anchor -my %id_to_html; - -# Build map of html pages links -print "Building map of section xml:ids to reference manual links...\n"; -while (my $file = pop @docbook) { - open FILE, $file or die "$!"; -# print "\nProcessing: $file\n\n"; - my $file_id; - while() { - if (/.* xml:id="([a-z0-9-]+?)"/) { - $file_id = $1; - last; - } - } - - $id_to_html{$file_id} = "$file_id.html"; - - while () { - next unless /.* xml:id="([a-z0-9-]+?)"/; -# print "$1\n"; - $id_to_html{$1} = "$file_id.html#$1"; - } - close FILE; -} - -# Get the list of class/interface names and their section ids/titles -print "Obtaining class and interface references from manual...\n"; -my @class_references = split /;/,`xsltproc --xinclude index-classes.xsl springsecurity.xml`; -# Get unique values -my %seen = (); -@class_references = grep { !$seen{$_}++} @class_references; -print "There are $#class_references references to classes and interfaces.\n"; - -my %id_to_title; -my %classnames_to_ids = (); - -foreach my $class_id_title (@class_references) { - (my $class, my $id, my $title) = split /:/, $class_id_title; - $title =~ s//>/; - $id_to_title{$id} = $title; - push( @{$classnames_to_ids{$class}}, $id ); -} - -print "Writing index file...\n"; -open INDEX, ">classindex.xml" || die "Couldn't open output file\n"; -print INDEX "\n"; -foreach my $class (sort keys %classnames_to_ids) { - print INDEX "\n"; - foreach my $id (@{$classnames_to_ids{$class}}) { - my $href = $id_to_html{$id}; - $index_page =~ /$href">([AB0-9\.]* )/; - my $section = $1 ? "$1" : ""; -# print "$id $href $section\n"; - my $title = $id_to_title{$id}; -# print "$section$title\n"; - print INDEX " \n"; - } - print INDEX "\n" - -} -print INDEX "\n"; -close INDEX; - -print "Generating HTML file...\n";  - -system("xsltproc class-index-html.xsl classindex.xml > class-index.html"); diff --git a/docs/manual/src/docbook/community.xml b/docs/manual/src/docbook/community.xml deleted file mode 100644 index 2fba097634..0000000000 --- a/docs/manual/src/docbook/community.xml +++ /dev/null @@ -1,48 +0,0 @@ - - - Spring Security Community - -
- - Issue Tracking - - Spring Security uses JIRA to manage bug reports and enhancement requests. If you find - a bug, please log a report using JIRA. Do not log it on the support forum, mailing list - or by emailing the project's developers. Such approaches are ad-hoc and we prefer to - manage bugs using a more formal process. - If possible, in your issue report please provide a JUnit test that demonstrates any - incorrect behaviour. Or, better yet, provide a patch that corrects the issue. Similarly, - enhancements are welcome to be logged in the issue tracker, although we only accept - enhancement requests if you include corresponding unit tests. This is necessary to - ensure project test coverage is adequately maintained. - You can access the issue tracker at http://jira.springsource.org/browse/SEC. -
-
- - Becoming Involved - - We welcome your involvement in the Spring Security project. There are many ways of - contributing, including reading the forum and responding to questions from other people, - writing new code, improving existing code, assisting with documentation, developing - samples or tutorials, or simply making suggestions. - -
-
- - Further Information - - Questions and comments on Spring Security are welcome. You can use the Spring - Community Forum web site at http://forum.springsource.org to discuss Spring Security with other users of the - framework. Remember to use JIRA for bug reports, as explained above. -
-
diff --git a/docs/manual/src/docbook/core-filters.xml b/docs/manual/src/docbook/core-filters.xml deleted file mode 100644 index b9aa392135..0000000000 --- a/docs/manual/src/docbook/core-filters.xml +++ /dev/null @@ -1,339 +0,0 @@ - - Core Security Filters - There are some key filters which will always be used in a web application which uses - Spring Security, so we'll look at these and their supporting classes and interfaces first. - We won't cover every feature, so be sure to look at the Javadoc for them if you want to get - the complete picture. -
- <classname>FilterSecurityInterceptor</classname> - We've already seen FilterSecurityInterceptor briefly when - discussing access-control in - general, and we've already used it with the namespace where the - <intercept-url> elements are combined to configure it internally. - Now we'll see how to explicitly configure it for use with a - FilterChainProxy, along with its companion filter - ExceptionTranslationFilter. A typical configuration example is - shown below: - - - - - - - - -]]> - FilterSecurityInterceptor is responsible for handling the - security of HTTP resources. It requires a reference to an - AuthenticationManager and an - AccessDecisionManager. It is also supplied with - configuration attributes that apply to different HTTP URL requests. Refer back to the original discussion on these in - the technical introduction. - The FilterSecurityInterceptor can be configured with - configuration attributes in two ways. The first, which is shown above, is using the - <filter-security-metadata-source> namespace element. This is - similar to the <http> element from the namespace chapter - but the <intercept-url> - child elements only use the pattern and access - attributes. Commas are used to delimit the different configuration attributes that apply - to each HTTP URL. The second option is to write your own - SecurityMetadataSource, but this is beyond the scope of - this document. Irrespective of the approach used, the - SecurityMetadataSource is responsible for returning a - List<ConfigAttribute> containing all of the configuration - attributes associated with a single secure HTTP URL. - It should be noted that the - FilterSecurityInterceptor.setSecurityMetadataSource() method actually - expects an instance of FilterInvocationSecurityMetadataSource. This - is a marker interface which subclasses - SecurityMetadataSource. It simply denotes the - SecurityMetadataSource understands - FilterInvocations. In the interests of simplicity we'll continue - to refer to the FilterInvocationSecurityMetadataSource as - a SecurityMetadataSource, as the distinction is of little - relevance to most users. - The SecurityMetadataSource created by the namespace - syntax obtains the configuration attributes for a particular - FilterInvocation by matching the request URL against the - configured pattern attributes. This behaves in the same way as it - does for namespace configuration. The default is to treat all expressions as Apache Ant - paths and regular expressions are also supported for more complex cases. The - path-type attribute is used to specify the type of pattern being - used. It is not possible to mix expression syntaxes within the same definition. As an - example, the previous configuration using regular expressions instead of Ant paths would - be written as follows: - - - - - - - - - - -]]> - Patterns are always evaluated in the order they are defined. Thus it is important that - more specific patterns are defined higher in the list than less specific patterns. This - is reflected in our example above, where the more specific - /secure/super/ pattern appears higher than the less specific - /secure/ pattern. If they were reversed, the - /secure/ pattern would always match and the - /secure/super/ pattern would never be evaluated. - -
-
- <classname>ExceptionTranslationFilter</classname> - The ExceptionTranslationFilter sits above the - FilterSecurityInterceptor in the security filter stack. It - doesn't do any actual security enforcement itself, but handles exceptions thrown by the - security interceptors and provides suitable and HTTP responses. - - - - - - - - - - - -]]> -
- <interfacename>AuthenticationEntryPoint</interfacename> - The AuthenticationEntryPoint will be called if the - user requests a secure HTTP resource but they are not authenticated. An appropriate - AuthenticationException or - AccessDeniedException will be thrown by a security - interceptor further down the call stack, triggering the - commence method on the entry point. This does the job of - presenting the appropriate response to the user so that authentication can begin. - The one we've used here is LoginUrlAuthenticationEntryPoint, - which redirects the request to a different URL (typically a login page). The actual - implementation used will depend on the authentication mechanism you want to be used - in your application. -
-
- <interfacename>AccessDeniedHandler</interfacename> - What happens if a user is already authenticated and they try to access a protected - resource? In normal usage, this shouldn't happen because the application workflow - should be restricted to operations to which a user has access. For example, an HTML - link to an administration page might be hidden from users who do not have an admin - role. You can't rely on hiding links for security though, as there's always a - possibility that a user will just enter the URL directly in an attempt to bypass the - restrictions. Or they might modify a RESTful URL to change some of the argument - values. Your application must be protected against these scenarios or it will - definitely be insecure. You will typically use simple web layer security to apply - constraints to basic URLs and use more specific method-based security on your - service layer interfaces to really nail down what is permissible. - If an AccessDeniedException is thrown and a user - has already been authenticated, then this means that an operation has been attempted - for which they don't have enough permissions. In this case, - ExceptionTranslationFilter will invoke a second strategy, the - AccessDeniedHandler. By default, an - AccessDeniedHandlerImpl is used, which just sends a 403 - (Forbidden) response to the client. Alternatively you can configure an instance - explicitly (as in the above example) and set an error page URL which it will - forwards the request to - We use a forward so that the SecurityContextHolder still contains details of - the principal, which may be useful for displaying to the user. In old releases - of Spring Security we relied upon the servlet container to handle a 403 error - message, which lacked this useful contextual information. - . This can be a simple access denied page, such as a JSP, - or it could be a more complex handler such as an MVC controller. And of course, you - can implement the interface yourself and use your own implementation. - It's also possible to supply a custom - AccessDeniedHandler when you're using the namespace - to configure your application. See the - namespace appendix for more details. -
-
- <interfacename>SavedRequest</interfacename>s and the <interfacename>RequestCache</interfacename> Interface - Another of ExceptionTranslationFilter's responsibilities is - to save the current request before invoking the AuthenticationEntryPoint. - This allows the request to be restored after the use has authenticated (see previous overview - of web authentication). - A typical example would be where the user logs in with a form, and is then redirected to the - original URL by the default SavedRequestAwareAuthenticationSuccessHandler - (see below). - - The RequestCache encapsulates the functionality required for storing - and retrieving HttpServletRequest instances. By default - the HttpSessionRequestCache is used, which stores the request - in the HttpSession. The RequestCacheFilter - has the job of actually restoring the saved request from the cache when the user is redirected to - the original URL. - - Under normal circumstances, you shouldn't need to modify any of this functionality, but the - saved-request handling is a best-effort approach and there may be situations which - the default configuration isn't able to handle. The use of these interfaces makes it fully pluggable - from Spring Security 3.0 onwards. - -
- -
-
- <classname>SecurityContextPersistenceFilter</classname> - We covered the purpose of this all-important filter in the Technical Overview chapter so - you might want to re-read that section at this point. Let's first take a look at how you - would configure it for use with a FilterChainProxy. A basic - configuration only requires the bean itself -]]> As we saw previously, this filter has two main tasks. It is responsible for - storage of the SecurityContext contents between HTTP requests and - for clearing the SecurityContextHolder when a request is - completed. Clearing the ThreadLocal in which the context is - stored is essential, as it might otherwise be possible for a thread to be replaced into - the servlet container's thread pool, with the security context for a particular user - still attached. This thread might then be used at a later stage, performing operations - with the wrong credentials. -
- <interfacename>SecurityContextRepository</interfacename> - From Spring Security 3.0, the job of loading and storing the security context is - now delegated to a separate strategy interface: - -public interface SecurityContextRepository { - SecurityContext loadContext(HttpRequestResponseHolder requestResponseHolder); - void saveContext(SecurityContext context, HttpServletRequest request, - HttpServletResponse response); -} - - The HttpRequestResponseHolder is simply a container for the - incoming request and response objects, allowing the implementation to replace these - with wrapper classes. The returned contents will be passed to the filter chain. - The default implementation is - HttpSessionSecurityContextRepository, which stores the - security context as an HttpSession attribute - In Spring Security 2.0 and earlier, this filter was called - HttpSessionContextIntegrationFilter and performed all the - work of storing the context was performed by the filter itself. If you were - familiar with this class, then most of the configuration options which were - available can now be found on - HttpSessionSecurityContextRepository. - . The most important configuration parameter for this implementation is - the allowSessionCreation property, which defaults to - true, thus allowing the class to create a session if it needs one - to store the security context for an authenticated user (it won't create one unless - authentication has taken place and the contents of the security context have - changed). If you don't want a session to be created, then you can set this property - to false: - - - - - - -]]> Alternatively you could provide an instance of - NullSecurityContextRepository, a null object - implementation, which will prevent the security context from being stored, even if a - session has already been created during the request. -
-
-
- <classname>UsernamePasswordAuthenticationFilter</classname> - We've now seen the three main filters which are always present in a Spring Security - web configuration. These are also the three which are automatically created by the - namespace <http> element and cannot be substituted with - alternatives. The only thing that's missing now is an actual authentication mechanism, - something that will allow a user to authenticate. This filter is the most commonly used - authentication filter and the one that is most often customized - For historical reasons, prior to Spring Security 3.0, this filter was called - AuthenticationProcessingFilter and the entry point was called - AuthenticationProcessingFilterEntryPoint. Since the framework - now supports many different forms of authentication, they have both been given more - specific names in 3.0. - . It also provides the implementation used by the - <form-login> element from the namespace. There are three stages - required to configure it. - - Configure a LoginUrlAuthenticationEntryPoint with the - URL of the login page, just as we did above, and set it on the - ExceptionTranslationFilter. - - - Implement the login page (using a JSP or MVC controller). - - - Configure an instance of - UsernamePasswordAuthenticationFilter in the application - context - - - Add the filter bean to your filter chain proxy (making sure you pay attention - to the order). - - The login form simply contains j_username and - j_password input fields, and posts to the URL that is monitored by - the filter (by default this is /j_spring_security_check). The basic - filter configuration looks something like this: - - - ]]> - -
- Application Flow on Authentication Success and Failure - The filter calls the configured - AuthenticationManager to process each authentication - request. The destination following a successful authentication or an authentication - failure is controlled by the - AuthenticationSuccessHandler and - AuthenticationFailureHandler strategy interfaces, - respectively. The filter has properties which allow you to set these so you can - customize the behaviour completely - In versions prior to 3.0, the application flow at this point had evolved to a - stage was controlled by a mix of properties on this class and strategy plugins. - The decision was made for 3.0 to refactor the code to make these two strategies - entirely responsible. - . Some standard implementations are supplied such as - SimpleUrlAuthenticationSuccessHandler, - SavedRequestAwareAuthenticationSuccessHandler, - SimpleUrlAuthenticationFailureHandler and - ExceptionMappingAuthenticationFailureHandler. Have a look at - the Javadoc for these classes and also for AbstractAuthenticationProcessingFilter - to get an overview of how they work and the supported features. - - If authentication is successful, the resulting - Authentication object will be placed into the - SecurityContextHolder. The configured - AuthenticationSuccessHandler will then be called to - either redirect or forward the user to the appropriate destination. By default a - SavedRequestAwareAuthenticationSuccessHandler is used, which - means that the user will be redirected to the original destination they requested - before they were asked to login. - The ExceptionTranslationFilter caches the original - request a user makes. When the user authenticates, the request handler makes use - of this cached request to obtain the original URL and redirect to it. The - original request is then rebuilt and used as an alternative. - If authentication fails, the configured - AuthenticationFailureHandler will be invoked. -
-
-
diff --git a/docs/manual/src/docbook/core-services.xml b/docs/manual/src/docbook/core-services.xml deleted file mode 100644 index 729fe8b019..0000000000 --- a/docs/manual/src/docbook/core-services.xml +++ /dev/null @@ -1,318 +0,0 @@ - - Core Services - Now that we have a high-level overview of the Spring Security architecture and its core - classes, let's take a closer look at one or two of the core interfaces and their - implementations, in particular the AuthenticationManager, - UserDetailsService and the - AccessDecisionManager. These crop up regularly throughout the - remainder of this document so it's important you know how they are configured and how they - operate. -
- The <interfacename>AuthenticationManager</interfacename>, - <classname>ProviderManager</classname> and - <classname>AuthenticationProvider</classname>s - The AuthenticationManager is just an interface, so the - implementation can be anything we choose, but how does it work in practice? What if we - need to check multiple authentication databases or a combination of different - authentication services such as a database and an LDAP server? - The default implementation in Spring Security is called - ProviderManager and rather than handling the authentication - request itself, it delegates to a list of configured - AuthenticationProviders, each of which is queried in turn to see - if it can perform the authentication. Each provider will either throw an exception or - return a fully populated Authentication object. Remember - our good friends, UserDetails and - UserDetailsService? If not, head back to the previous - chapter and refresh your memory. The most common approach to verifying an authentication - request is to load the corresponding UserDetails and - check the loaded password against the one that has been entered by the user. This is the - approach used by the DaoAuthenticationProvider (see below). The - loaded UserDetails object - and particularly the - GrantedAuthoritys it contains - will be used when building the fully - populated Authentication object which is returned from a - successful authentication and stored in the SecurityContext. - If you are using the namespace, an instance of ProviderManager - is created and maintained internally, and you add providers to it by using the namespace - authentication provider elements (see the namespace - chapter). In this case, you should not declare a - ProviderManager bean in your application context. However, if you - are not using the namespace then you would declare it like so: - - - - - - - -]]> - In the above example we have three providers. They are tried in the order shown (which - is implied by the use of a List), with each provider able to attempt - authentication, or skip authentication by simply returning null. If - all implementations return null, the ProviderManager will throw a - ProviderNotFoundException. If you're interested in - learning more about chaining providers, please refer to the - ProviderManager JavaDocs. - Authentication mechanisms such as a web form-login processing filter are injected - with a reference to the ProviderManager and will call it - to handle their authentication requests. The providers you require will sometimes be - interchangeable with the authentication mechanisms, while at other times they will - depend on a specific authentication mechanism. For example, - DaoAuthenticationProvider and - LdapAuthenticationProvider are compatible with any mechanism - which submits a simple username/password authentication request and so will work with - form-based logins or HTTP Basic authentication. On the other hand, some authentication - mechanisms create an authentication request object which can only be interpreted by a - single type of AuthenticationProvider. An example of this would - be JA-SIG CAS, which uses the notion of a service ticket and so can therefore only be - authenticated by a CasAuthenticationProvider. You needn't be too - concerned about this, because if you forget to register a suitable provider, you'll - simply receive a ProviderNotFoundException when an attempt to - authenticate is made. -
- Erasing Credentials on Successful Authentication - By default (from Spring Security 3.1 onwards) the - ProviderManager will attempt to clear any sensitive - credentials information from the Authentication - object which is returned by a successful authentication request. This prevents - information like passwords being retained longer than necessary. - This may cause issues when you are using a cache of user objects, for example, to - improve performance in a stateless application. If the - Authentication contains a reference to an object in - the cache (such as a UserDetails instance) and this - has its credentials removed, then it will no longer be possible to authenticate - against the cached value. You need to take this into account if you are using a - cache. An obvious solution is to make a copy of the object first, either in the - cache implementation or in the AuthenticationProvider - which creates the returned Authentication object. - Alternatively, you can disable the - eraseCredentialsAfterAuthentication property on - ProviderManager. See the Javadoc for more information. - -
-
- <literal>DaoAuthenticationProvider</literal> - The simplest AuthenticationProvider implemented by - Spring Security is DaoAuthenticationProvider, which is also one - of the earliest supported by the framework. It leverages a - UserDetailsService (as a DAO) in order to lookup the - username, password and GrantedAuthoritys. It - authenticates the user simply by comparing the password submitted in a - UsernamePasswordAuthenticationToken against the one loaded by - the UserDetailsService. Configuring the provider is - quite simple: - - -]]> The PasswordEncoder is optional. A - PasswordEncoder provides encoding and decoding of - passwords presented in the UserDetails object that is - returned from the configured UserDetailsService. This - will be discussed in more detail below. -
-
-
- <interfacename>UserDetailsService</interfacename> Implementations - As mentioned in the earlier in this reference guide, most authentication providers - take advantage of the UserDetails and - UserDetailsService interfaces. Recall that the contract - for UserDetailsService is a single method: - - - UserDetails loadUserByUsername(String username) throws UsernameNotFoundException; - - - The returned UserDetails is an interface that provides - getters that guarantee non-null provision of authentication information such as the - username, password, granted authorities and whether the user account is enabled or - disabled. Most authentication providers will use a - UserDetailsService, even if the username and password are - not actually used as part of the authentication decision. They may use the returned - UserDetails object just for its - GrantedAuthority information, because some other system (like LDAP or - X.509 or CAS etc) has undertaken the responsibility of actually validating the - credentials. - Given UserDetailsService is so simple to implement, it - should be easy for users to retrieve authentication information using a persistence - strategy of their choice. Having said that, Spring Security does include a couple of - useful base implementations, which we'll look at below. -
- In-Memory Authentication - Is easy to use create a custom UserDetailsService - implementation that extracts information from a persistence engine of choice, but - many applications do not require such complexity. This is particularly true if - you're building a prototype application or just starting integrating Spring - Security, when you don't really want to spend time configuring databases or writing - UserDetailsService implementations. For this sort of - situation, a simple option is to use the user-service element - from the security namespace: - - - - ]]> - This also supports the use of an external properties - file: - ]]> The properties file should contain entries in the form - username=password,grantedAuthority[,grantedAuthority][,enabled|disabled] - For example - - jimi=jimispassword,ROLE_USER,ROLE_ADMIN,enabled - bob=bobspassword,ROLE_USER,enabled -
-
- <literal>JdbcDaoImpl</literal> - Spring Security also includes a UserDetailsService - that can obtain authentication information from a JDBC data source. Internally - Spring JDBC is used, so it avoids the complexity of a fully-featured object - relational mapper (ORM) just to store user details. If your application does use an - ORM tool, you might prefer to write a custom - UserDetailsService to reuse the mapping files you've - probably already created. Returning to JdbcDaoImpl, an example - configuration is shown below: - - - - - - - - - - - ]]> - - You can use different relational database management systems by modifying the - DriverManagerDataSource shown above. You can also use a global - data source obtained from JNDI, as with any other Spring configuration. -
- Authority Groups - By default, JdbcDaoImpl loads the authorities for a - single user with the assumption that the authorities are mapped directly to - users (see the database schema - appendix). An alternative approach is to partition the authorities into - groups and assign groups to the user. Some people prefer this approach as a - means of administering user rights. See the JdbcDaoImpl - Javadoc for more information on how to enable the use of group authorities. The - group schema is also included in the appendix. -
- -
-
-
- Password Encoding - Spring Security's - PasswordEncoder interface is used to support the use of - passwords which are encoded in some way in persistent storage. You should never store - passwords in plain text. Always use a one-way password hashing algorithm such as bcrypt - which uses a built-in salt value which is different for each stored password. Do not use - a plain hash function such as MD5 or SHA, or even a salted version. Bcrypt is deliberately - designed to be slow and to hinder offline password cracking, whereas standard hash algorithms - are fast and can easily be used to test thousands of passwords in parallel on custom - hardware. You might think this doesn't apply to you since your password database is - secure and offline attacks aren't a risk. If so, do some research and read up on all - the high-profile sites which have been compromised in this way and have been pilloried - for storing their passwords insecurely. It's best to be on the safe side. Using - org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder" - is a good choice for security. There are also compatible implementations in other common - programming languages so it a good choice for interoperability too. - - If you are using a legacy system which already has hashed passwords, then you will - need to use an encoder which matches your current algorithm, at least until you can - migrate your users to a more secure scheme (usually this will involve asking the user - to set a new password, since hashes are irreversible). Spring Security has a package - containing legacy password encoding implementation, namely, - org.springframework.security.authentication.encoding. - The DaoAuthenticationProvider can be injected - with either the new or legacy PasswordEncoder - types. -
- What is a hash? - Password hashing is not unique to Spring Security but is a common source of - confusion for users who are not familiar with the concept. A hash (or digest) - algorithm is a one-way function which produces a piece of fixed-length output data - (the hash) from some input data, such as a password. As an example, the MD5 hash of - the string password (in hexadecimal) is - - 5f4dcc3b5aa765d61d8327deb882cf99 - - A hash is one-way in the sense that it is very difficult (effectively - impossible) to obtain the original input given the hash value, or indeed any - possible input which would produce that hash value. This property makes hash values - very useful for authentication purposes. They can be stored in your user database as - an alternative to plaintext passwords and even if the values are compromised they do - not immediately reveal a password which can be used to login. Note that this also - means you have no way of recovering the password once it is encoded. -
-
- Adding Salt to a Hash - One potential problem with the use of password hashes that it is relatively easy - to get round the one-way property of the hash if a common word is used for the - input. People tend to choose similar passwords and huge dictionaries of these from - previously hacked sites are available online. For example, if you search for the hash value - 5f4dcc3b5aa765d61d8327deb882cf99 using google, you will quickly - find the original word password. In a similar way, an attacker can - build a dictionary of hashes from a standard word list and use this to lookup the - original password. One way to help prevent this is to have a suitably strong - password policy to try to prevent common words from being used. Another is to use a - salt when calculating the hashes. This is an additional string of - known data for each user which is combined with the password before calculating the - hash. Ideally the data should be as random as possible, but in practice any salt - value is usually preferable to none. Using a salt means that an attacker has to - build a separate dictionary of hashes for each salt value, making the attack more - complicated (but not impossible). - Bcrypt automatically generates a random salt value for each password when it - is encoded, and stores it in the bcrypt string in a standard format. - The legacy approach to handling salt was to inject a - SaltSource into the - DaoAuthenticationProvider, which would obtain a salt - value for a particular user and pass it to the - PasswordEncoder. Using bcrypt means you don't have - worry about the details of salt handling (such as where the the value is stored), - as it is all done internally. So we'd strongly recommend you use bcrypt - unless you already have a system in place which stores the salt separately. - -
-
- Hashing and Authentication - When an authentication provider (such as Spring Security's - DaoAuthenticationProvider) needs to check the password in a - submitted authentication request against the known value for a user, and the stored - password is encoded in some way, then the submitted value must be encoded using - exactly the same algorithm. It's up to you to check that these are compatible as - Spring Security has no control over the persistent values. If you add password - hashing to your authentication configuration in Spring Security, and your database - contains plaintext passwords, then there is no way authentication can succeed. Even - if you are aware that your database is using MD5 to encode the passwords, for - example, and your application is configured to use Spring Security's - Md5PasswordEncoder, there are still things that can go wrong. - The database may have the passwords encoded in Base 64, for example while the - encoder is using hexadecimal strings (the default). Alternatively your database may - be using upper-case while the output from the encoder is lower-case. Make sure you - write a test to check the output from your configured password encoder with a known - password and salt combination and check that it matches the database value before - going further and attempting to authenticate through your application. Using a standard - like bcrypt will avoid these issues. - - If you want to generate encoded passwords directly in Java for storage in your - user database, then you can use the encode method on the - PasswordEncoder. -
-
-
diff --git a/docs/manual/src/docbook/crypto.xml b/docs/manual/src/docbook/crypto.xml deleted file mode 100644 index 000520d433..0000000000 --- a/docs/manual/src/docbook/crypto.xml +++ /dev/null @@ -1,138 +0,0 @@ - - - Spring Security Crypto Module - -
- Introduction - - The Spring Security Crypto module provides support for symmetric encryption, key generation, and password encoding. - The code is distributed as part of the core module but has no dependencies on any other Spring Security (or Spring) code. - -
- -
- Encryptors - - The Encryptors class provides factory methods for constructing symmetric encryptors. - Using this class, you can create ByteEncryptors to encrypt data in raw byte[] form. - You can also construct TextEncryptors to encrypt text strings. - Encryptors are thread safe. - -
- BytesEncryptor - - Use the Encryptors.standard factory method to construct a "standard" BytesEncryptor: - - - The "standard" encryption method is 256-bit AES using PKCS #5's PBKDF2 (Password-Based Key Derivation Function #2). - This method requires Java 6. - The password used to generate the SecretKey should be kept in a secure place and not be shared. - The salt is used to prevent dictionary attacks against the key in the event your encrypted data is compromised. - A 16-byte random initialization vector is also applied so each encrypted message is unique. - - - The provided salt should be in hex-encoded String form, be random, and be at least 8 bytes in length. - Such a salt may be generated using a KeyGenerator: - - - -
-
- TextEncryptor - - Use the Encryptors.text factory method to construct a standard TextEncryptor: - - - A TextEncryptor uses a standard BytesEncryptor to encrypt text data. - Encrypted results are returned as hex-encoded strings for easy storage on the filesystem or in the database. - - - Use the Encryptors.queryableText factory method to construct a "queryable" TextEncryptor: - - - The difference between a queryable TextEncryptor and a standard TextEncryptor has to do with initialization vector (iv) handling. - The iv used in a queryable TextEncryptor#encrypt operation is shared, or constant, and is not randomly generated. - This means the same text encrypted multiple times will always produce the same encryption result. - This is less secure, but necessary for encrypted data that needs to be queried against. - An example of queryable encrypted text would be an OAuth apiKey. - -
-
- -
- Key Generators - - The KeyGenerators class provides a number of convenience factory methods for constructing different types of key generators. - Using this class, you can create a BytesKeyGenerator to generate byte[] keys. - You can also construct a StringKeyGenerator to generate string keys. - KeyGenerators are thread safe. - -
- BytesKeyGenerator - - Use the KeyGenerators.secureRandom factory methods to generate a BytesKeyGenerator backed by a SecureRandom instance: - - - - - The default key length is 8 bytes. - There is also a KeyGenerators.secureRandom variant that provides control over the key length: - - - - - Use the KeyGenerators.shared factory method to construct a BytesKeyGenerator that always returns the same key on every invocation: - - - -
-
- StringKeyGenerator - - Use the KeyGenerators.string factory method to construct a 8-byte, SecureRandom KeyGenerator that hex-encodes each key as a String: - - - -
-
- -
- Password Encoding - - The password package of the spring-security-crypto module provides support for encoding passwords. - PasswordEncoder is the central service interface and has the following signature: - - - The matches method returns true if the rawPassword, once encoded, equals the encodedPassword. - This method is designed to support password-based authentication schemes. - - - The BCryptPasswordEncoder implementation uses the widely supported "bcrypt" algorithm - to hash the passwords. Bcrypt uses a random 16 byte salt value and is a deliberately slow algorithm, in order to - hinder password crackers. The amount of work it does can be tuned using the "strength" parameter which takes values - from 4 to 31. The higher the value, the more work has to be done to calculate the hash. The default value is 10. - You can change this value in your deployed system without affecting existing passwords, as the value is also stored - in the encoded hash. - - - -
- -
diff --git a/docs/manual/src/docbook/csrf.xml b/docs/manual/src/docbook/csrf.xml deleted file mode 100644 index b9e4d7691e..0000000000 --- a/docs/manual/src/docbook/csrf.xml +++ /dev/null @@ -1,331 +0,0 @@ - - - Cross Site Request Forgery (CSRF) - - This section discusses Spring Security's - Cross Site Request Forgery (CSRF) support. -
- CSRF Attacks - Before we discuss how Spring Security can protect applications from CSRF attacks, we will explain what a CSRF - attack is. Let's take a look at a concrete example to get a better understanding. - Assume that your bank's website provides a form that allows transferring money from the currently logged in user - to another bank account. For example, the HTTP request might look like: - - Now pretend you authenticate to your bank's website and then, without logging out, visit an evil website. The evil - website contains an HTML page with the following form: - - - - - -]]> - You like to win money, so you click on the submit button. In the process, you have unintentionally transferred $100 to - a malicious user. This happens because, while the evil website cannot see your cookies, the cookies associated with your - bank are still sent along with the request. - Worst yet, this whole process could have been automated using JavaScript. This means you didn't even need to click on the - button. So how do we protect ourselves from such attacks? -
-
- Synchronizer Token Pattern - The issue is that the HTTP request from the bank's website and the request from the evil website are exactly the same. This - means there is no way to reject requests coming from the evil website and allow requests coming from the bank's website. To - protect against CSRF attacks we need to ensure there is something in the request that the evil site is unable to provide. - One solution is to use the - Synchronizer - Token Pattern. This solution is to ensure that each request requires, in addition to our session cookie, a randomly - generated token as an HTTP parameter. When a request is submitted, the server must look up the expected value for the parameter - and compare it against the actual value in the request. If the values do not match, the request should fail. - We can relax the expectations to only require the token for each HTTP request that updates state. This can be safely done - since the same origin policy ensures the evil site cannot read the response. Additionally, we do not want to include the random - token in HTTP GET as this can cause the tokens to be leaked. - Let's take a look at how our example would change. Assume the randomly generated token is present in an HTTP parameter named - _csrf. For example, the request to transfer money would look like this: - -]]> - You will notice that we added the _csrf parameter with a random value. Now the evil website will not be able to guess the - correct value for the _csrf parameter (which must be explicitly provided on the evil website) and the transfer will fail when the - server compares the actual token to the expected token. -
-
- When to use CSRF protection - When you use CSRF protection? Our recommendation is to use CSRF protection for any request that could be processed by a browser by normal users. If you are only creating - a service that is used by non-browser clients, you will likely want to disable CSRF protection. -
- CSRF protection and JSON - A common question is, but do I need to protect JSON requests made by javascript? The short answer is, it depends. However, you must be very careful as there - are CSRF exploits that can impact JSON requests. For example, a malicious user can create a - CSRF with JSON using the following form: - - - -]]> - This will produce the following JSON structure - - If an application were not validating the Content-Type, then it would be exposed to this exploit. Depending on the setup, a Spring MVC application that validates the - Content-Type could still be exploited by updating the URL suffix to end with ".json" as shown below: - - - -]]> -
-
- CSRF and Stateless Browser Applications - What if my application is stateless? That doesn't necessarily mean you are protected. In fact, if a user does not need to perform any actions in the web browser for a given - request, they are likely still vulnerable to CSRF attacks. - For example, consider an application uses a custom cookie that contains all the state within it for authentication instead of the JSESSIONID. When the CSRF attack is made - the custom cookie will be sent with the request in the same manner that the JSESSIONID cookie was sent in our previous example. - User's using basic authentication are also vulnerable to CSRF attacks since the browser will automatically include the username password in any requests in the same manner that - the JSESSIONID cookie was sent in our previous example. -
-
-
- Using Spring Security CSRF Protection - So what are the steps necessary to use Spring Security's to protect our site against CSRF attacks? The steps to using Spring - Security's CSRF protection are outlined below: - - - Use proper HTTP verbs - - - Configure CSRF Protection - - - Include the CSRF Token - - -
- Use proper HTTP verbs - The first step to protecting against CSRF attacks is to ensure your website uses proper HTTP verbs. Specifically, before Spring - Security's CSRF support can be of use, you need to be certain that your application is using PATCH, POST, PUT, and/or DELETE for anything - that modifies state. - This is not a limitation of Spring Security's support, but instead a general requirement for proper CSRF prevention. The reason is that - including private information in an HTTP GET can cause the information to be leaked. See - RFC 2616 Section 15.1.3 Encoding Sensitive Information in URI's for - general guidance on using POST instead of GET for sensitive information. -
-
- Configure CSRF Protection - The next step is to include Spring Security's CSRF protection within your application. Some frameworks handle invalid CSRF tokens by invaliding the user's - session, but this causes its own problems. Instead by default Spring Security's CSRF protection will produce an HTTP 403 access denied. - This can be customized by configuring the AccessDeniedHandler to process InvalidCsrfTokenException - differently. - For passivity reasons, if you are using the XML configuration, CSRF protection must be explicitly enabled using the <csrf> element. Refer to the - <csrf> element's documentation for additional customizations. - - SEC-2347 is logged to ensure Spring - Security 4.x's XML namespace configuration will enable CSRF protection by default. - - - - - -]]> - CSRF protection is enabled by default with Java configuration. If you would like to disable CSRF, the corresponding Java configuration can be - seen below. Refer to the Javadoc of csrf() for additional customizations in how CSRF protection is configured. - -
-
- Include the CSRF Token -
- Form Submissions - The last step is to ensure that you include the CSRF token in all PATCH, POST, PUT, and DELETE methods. This can be done using - the _csrf request attribute to obtain the current CsrfToken. An example of doing this with a JSP is shown below: - -
- - -
]]>
- - If you are using Spring MVC <form:form> tag, the CsrfToken is automatically included for you using the CsrfRequestDataValueProcessor. - -
-
- Ajax and JSON Requests - If you using JSON, then it is not possible to submit the CSRF token within an HTTP parameter. Instead you can submit the token within a HTTP header. - A typical pattern would be to include the CSRF token within your meta tags. An example with a JSP is shown below: - - - - - - - - ]]> - You can then include the token within all your Ajax requests. If you were using jQuery, this could be done with the following: - - As a alternative to jQuery, we recommend using cujoJS’s rest.js. rest.js provides - advanced support for working with HTTP request and responses in RESTful ways. A core capability is the ability to contextualize the HTTP client adding behavior as needed by - chaining interceptors on to the client. - - The configured client can be shared with any component of the application that needs to make a request to the CSRF protected resource. One significant different between rest.js - and jQuery is that only requests made with the configured client will contain the CSRF token, vs jQuery where all requests will include the token. The ability - to scope which requests receive the token helps guard against leaking the CSRF token to a third party. Please refer to the - rest.js reference documentation for more information on rest.js. -
-
-
-
- CSRF Caveats - There are a few caveats when implementing CSRF. -
- Timeouts - One issue is that the expected CSRF token is stored in the HttpSession, so as soon as the HttpSession expires your configured - AccessDeniedHandler will receive a InvalidCsrfTokenException. If you are using the default - AccessDeniedHandler, the browser will get an HTTP 403 and display a poor error message. - - One might ask why the expected CsrfToken isn't stored in a cookie. This is because there are known exploits in which headers - (i.e. specify the cookies) can be set by another domain. This is the same reason Ruby on Rails - no longer skips CSRF checks when the header X-Requested-With - is present. See this webappsec.org thread - for details on how to perform the exploit. Another disadvantage is that by removing the state (i.e. the timeout) you lose the ability - to forcibly terminate the token if something got compromised. - - A simple way to mitigate an active user experiencing a timeout is to have some JavaScript that lets the user know their session is about to expire. - The user can click a button to continue and refresh the session. - Alternatively, specifying a custom AccessDeniedHandler allows you to process the InvalidCsrfTokenException - anyway you like. For an example of how to customize the AccessDeniedHandler refer to the provided links for both - xml and - Java - configuration. -
-
- Logging In - In order to protect against forging log in requests the log in form should be protected against CSRF attacks too. Since the CsrfToken is stored in - HttpSession, this means an HttpSession will be created as soon as CsrfToken token attribute is accessed. While this sounds bad in - a RESTful / stateless architecture the reality is that state is necessary to implement practical security. Without state, we have nothing we can do if a token is - compromised. Practically speaking, the CSRF token is quite small in size and should have a negligible impact on our architecture. -
-
- Logging Out - Adding CSRF will update the LogoutFilter to only use HTTP POST. This ensures that log out requires a CSRF token and that a malicious user cannot forcibly - log out your users. - One approach is to use a form for log out. If you really want a link, you can use JavaScript to have the link perform a POST (i.e. maybe on a hidden form). For - browsers with JavaScript that is disabled, you can optionally have the link take the user to a log out confirmation page that will perform the POST. -
-
- Multipart (file upload) - There are two options to using CSRF protection with multipart/form-data. Each option has its tradeoffs. - - - Placing MultipartFilter before Spring Security - - - Include CSRF token in action - - - - More information about using multipart forms with Spring can be found within the - 17.10 Spring's multipart (file upload) - support section of the Spring reference. - -
- Placing MultipartFilter before Spring Security - The first option is to ensure that the MultipartFilter is specified before the Spring - Security filter. Specifying the MultipartFilter after the Spring Security filter means that there is no authorization for invoking the - MultipartFilter which means anyone can place temporary files on your server. However, only authorized users will be able to submit a File that is processed - by your application. In general, this is the recommended approach because the temporary file upload should have a negligble impact on most servers. - To ensure MultipartFilter is specified before the Spring Security filter with java configuration, users can override beforeSpringSecurityFilterChain as - shown below: - - To ensure MultipartFilter is specified before the Spring Security filter with XML configuration, users can ensure the <filter-mapping> element - of the MultipartFilter is placed before the springSecurityFilterChain within the web.xml as shown below: - - MultipartFilter - org.springframework.web.multipart.support.MultipartFilter - - - springSecurityFilterChain - org.springframework.web.filter.DelegatingFilterProxy - - - MultipartFilter - /* - - - springSecurityFilterChain - /* - -]]> -
-
- Include CSRF token in action - If allowing unauthorized users to upload temporariy files is not acceptable, an alternative is to place the MultipartFilter after the Spring Security - filter and include the CSRF as a query parameter in the action attribute of the form. An example with a jsp is shown below - ]]> - The disadvantage to this approach is that query parameters can be leaked. More genearlly, - it is considered best practice to place sensitive data within the body or headers to ensure it is not leaked. Additional information can be found in - RFC 2616 Section 15.1.3 Encoding Sensitive Information in URI's. -
-
-
- HiddenHttpMethodFilter - The HiddenHttpMethodFilter should be placed before the Spring Security filter. In general this is true, but it could have additional implications when - protecting against CSRF attacks. - Note that the HiddenHttpMethodFilter only overrides the HTTP method on a POST, so this is actually unlikely to cause any real problems. However, it is still - best practice to ensure it is placed before Spring Security's filters. -
-
-
- Overriding Defaults - Spring Security's goal is to provide defaults that protect your users from exploits. This does not mean that you are forced to accept all of its defaults. - For example, you can provide a custom CsrfTokenRepository to override the way in which the CsrfToken is stored. - You can also specify a custom RequestMatcher to determine which requests are protected by CSRF (i.e. perhaps you don't care if log out is exploited). In short, if - Spring Security's CSRF protection doesn't behave exactly as you want it, you are able to customize the behavior. Refer to the <csrf> - documentation for details on how to make these customizations with XML and the CsrfConfigurer javadoc for details on how to make these - customizations when using Java configuration. -
-
diff --git a/docs/manual/src/docbook/domain-acls.xml b/docs/manual/src/docbook/domain-acls.xml deleted file mode 100644 index 2eaaf85b83..0000000000 --- a/docs/manual/src/docbook/domain-acls.xml +++ /dev/null @@ -1,294 +0,0 @@ - - - Domain Object Security (ACLs) - -
- - Overview - - Complex applications often will find the need to define access permissions not simply - at a web request or method invocation level. Instead, security decisions need to - comprise both who (Authentication), where - (MethodInvocation) and what - (SomeDomainObject). In other words, authorization decisions also need - to consider the actual domain object instance subject of a method invocation. - Imagine you're designing an application for a pet clinic. There will be two main - groups of users of your Spring-based application: staff of the pet clinic, as well as - the pet clinic's customers. The staff will have access to all of the data, whilst your - customers will only be able to see their own customer records. To make it a little more - interesting, your customers can allow other users to see their customer records, such as - their "puppy preschool" mentor or president of their local "Pony Club". Using Spring - Security as the foundation, you have several approaches that can be used: - - Write your business methods to enforce the security. You could consult a - collection within the Customer domain object instance to - determine which users have access. By using the - SecurityContextHolder.getContext().getAuthentication(), - you'll be able to access the Authentication - object. - - - Write an AccessDecisionVoter to enforce the - security from the GrantedAuthority[]s stored in the - Authentication object. This would mean your - AuthenticationManager would need to populate the - Authentication with custom - GrantedAuthority[]s representing each of the - Customer domain object instances the principal has access - to. - - - Write an AccessDecisionVoter to enforce the - security and open the target Customer domain object directly. - This would mean your voter needs access to a DAO that allows it to retrieve the - Customer object. It would then access the - Customer object's collection of approved users and make the - appropriate decision. - - - Each one of these approaches is perfectly legitimate. However, the first couples your - authorization checking to your business code. The main problems with this include the - enhanced difficulty of unit testing and the fact it would be more difficult to reuse the - Customer authorization logic elsewhere. Obtaining the - GrantedAuthority[]s from the - Authentication object is also fine, but will not scale to - large numbers of Customers. If a user might be able to access 5,000 - Customers (unlikely in this case, but imagine if it were a popular - vet for a large Pony Club!) the amount of memory consumed and time required to construct - the Authentication object would be undesirable. The final - method, opening the Customer directly from external code, is probably - the best of the three. It achieves separation of concerns, and doesn't misuse memory or - CPU cycles, but it is still inefficient in that both the - AccessDecisionVoter and the eventual business method - itself will perform a call to the DAO responsible for retrieving the - Customer object. Two accesses per method invocation is clearly - undesirable. In addition, with every approach listed you'll need to write your own - access control list (ACL) persistence and business logic from scratch. - Fortunately, there is another alternative, which we'll talk about below. -
-
- - Key Concepts - - Spring Security's ACL services are shipped in the - spring-security-acl-xxx.jar. You will need to add this JAR to your - classpath to use Spring Security's domain object instance security capabilities. - Spring Security's domain object instance security capabilities centre on the concept - of an access control list (ACL). Every domain object instance in your system has its own - ACL, and the ACL records details of who can and can't work with that domain object. With - this in mind, Spring Security delivers three main ACL-related capabilities to your application: - - A way of efficiently retrieving ACL entries for all of your domain objects - (and modifying those ACLs) - - - A way of ensuring a given principal is permitted to work with your objects, - before methods are called - - - A way of ensuring a given principal is permitted to work with your objects (or - something they return), after methods are called - - - As indicated by the first bullet point, one of the main capabilities of the Spring - Security ACL module is providing a high-performance way of retrieving ACLs. This ACL - repository capability is extremely important, because every domain object instance in - your system might have several access control entries, and each ACL might inherit from - other ACLs in a tree-like structure (this is supported out-of-the-box by Spring - Security, and is very commonly used). Spring Security's ACL capability has been - carefully designed to provide high performance retrieval of ACLs, together with - pluggable caching, deadlock-minimizing database updates, independence from ORM - frameworks (we use JDBC directly), proper encapsulation, and transparent database - updating. - Given databases are central to the operation of the ACL module, let's explore the four - main tables used by default in the implementation. The tables are presented below in - order of size in a typical Spring Security ACL deployment, with the table with the most - rows listed last: - - - ACL_SID allows us to uniquely identify any principal or authority in the - system ("SID" stands for "security identity"). The only columns are the ID, a - textual representation of the SID, and a flag to indicate whether the textual - representation refers to a principal name or a - GrantedAuthority. Thus, there is a single row for - each unique principal or GrantedAuthority. When - used in the context of receiving a permission, a SID is generally called a - "recipient". - - - ACL_CLASS allows us to uniquely identify any domain object class in the - system. The only columns are the ID and the Java class name. Thus, there is a - single row for each unique Class we wish to store ACL permissions for. - - - ACL_OBJECT_IDENTITY stores information for each unique domain object instance - in the system. Columns include the ID, a foreign key to the ACL_CLASS table, a - unique identifier so we know which ACL_CLASS instance we're providing - information for, the parent, a foreign key to the ACL_SID table to represent the - owner of the domain object instance, and whether we allow ACL entries to inherit - from any parent ACL. We have a single row for every domain object instance we're - storing ACL permissions for. - - - Finally, ACL_ENTRY stores the individual permissions assigned to each - recipient. Columns include a foreign key to the ACL_OBJECT_IDENTITY, the - recipient (ie a foreign key to ACL_SID), whether we'll be auditing or not, and - the integer bit mask that represents the actual permission being granted or - denied. We have a single row for every recipient that receives a permission to - work with a domain object. - - - As mentioned in the last paragraph, the ACL system uses integer bit masking. Don't - worry, you need not be aware of the finer points of bit shifting to use the ACL system, - but suffice to say that we have 32 bits we can switch on or off. Each of these bits - represents a permission, and by default the permissions are read (bit 0), write (bit 1), - create (bit 2), delete (bit 3) and administer (bit 4). It's easy to implement your own - Permission instance if you wish to use other permissions, and the - remainder of the ACL framework will operate without knowledge of your extensions. - It is important to understand that the number of domain objects in your system has - absolutely no bearing on the fact we've chosen to use integer bit masking. Whilst you - have 32 bits available for permissions, you could have billions of domain object - instances (which will mean billions of rows in ACL_OBJECT_IDENTITY and quite probably - ACL_ENTRY). We make this point because we've found sometimes people mistakenly believe - they need a bit for each potential domain object, which is not the case. - Now that we've provided a basic overview of what the ACL system does, and what it - looks like at a table structure, let's explore the key interfaces. The key interfaces - are: - - - Acl: Every domain object has one and only one - Acl object, which internally holds the - AccessControlEntrys as well as knows the owner of the - Acl. An Acl does not refer directly to the domain object, but - instead to an ObjectIdentity. The Acl is - stored in the ACL_OBJECT_IDENTITY table. - - - AccessControlEntry: An Acl holds - multiple AccessControlEntrys, which are often abbreviated as - ACEs in the framework. Each ACE refers to a specific tuple of - Permission, Sid and - Acl. An ACE can also be granting or non-granting and contain - audit settings. The ACE is stored in the ACL_ENTRY table. - - - Permission: A permission represents a particular immutable - bit mask, and offers convenience functions for bit masking and outputting - information. The basic permissions presented above (bits 0 through 4) are - contained in the BasePermission class. - - - Sid: The ACL module needs to refer to principals and - GrantedAuthority[]s. A level of indirection is provided by - the Sid interface, which is an abbreviation of "security - identity". Common classes include PrincipalSid (to represent - the principal inside an Authentication object) - and GrantedAuthoritySid. The security identity information is - stored in the ACL_SID table. - - - ObjectIdentity: Each domain object is represented - internally within the ACL module by an ObjectIdentity. The - default implementation is called ObjectIdentityImpl. - - - AclService: Retrieves the Acl applicable - for a given ObjectIdentity. In the included implementation - (JdbcAclService), retrieval operations are delegated to a - LookupStrategy. The LookupStrategy - provides a highly optimized strategy for retrieving ACL information, using - batched retrievals (BasicLookupStrategy) and supporting - custom implementations that leverage materialized views, hierarchical queries - and similar performance-centric, non-ANSI SQL capabilities. - - - MutableAclService: Allows a modified Acl - to be presented for persistence. It is not essential to use this interface if - you do not wish. - - - Please note that our out-of-the-box AclService and related database classes all use - ANSI SQL. This should therefore work with all major databases. At the time of writing, - the system had been successfully tested using Hypersonic SQL, PostgreSQL, Microsoft SQL - Server and Oracle. - Two samples ship with Spring Security that demonstrate the ACL module. The first is - the Contacts Sample, and the other is the Document Management System (DMS) Sample. We - suggest taking a look over these for examples. -
-
- - Getting Started - - To get starting using Spring Security's ACL capability, you will need to store your - ACL information somewhere. This necessitates the instantiation of a - DataSource using Spring. The DataSource is then - injected into a JdbcMutableAclService and - BasicLookupStrategy instance. The latter provides high-performance - ACL retrieval capabilities, and the former provides mutator capabilities. Refer to one - of the samples that ship with Spring Security for an example configuration. You'll also - need to populate the database with the four ACL-specific tables listed in the last - section (refer to the ACL samples for the appropriate SQL statements). - Once you've created the required schema and instantiated - JdbcMutableAclService, you'll next need to ensure your domain model - supports interoperability with the Spring Security ACL package. Hopefully - ObjectIdentityImpl will prove sufficient, as it provides a large - number of ways in which it can be used. Most people will have domain objects that - contain a public Serializable getId() method. If the return type is - long, or compatible with long (eg an int), you will find you need not give further - consideration to ObjectIdentity issues. Many parts of the ACL module - rely on long identifiers. If you're not using long (or an int, byte etc), there is a - very good chance you'll need to reimplement a number of classes. We do not intend to - support non-long identifiers in Spring Security's ACL module, as longs are already - compatible with all database sequences, the most common identifier data type, and are of - sufficient length to accommodate all common usage scenarios. - The following fragment of code shows how to create an Acl, or - modify an existing - Acl:// Prepare the information we'd like in our access control entry (ACE) -ObjectIdentity oi = new ObjectIdentityImpl(Foo.class, new Long(44)); -Sid sid = new PrincipalSid("Samantha"); -Permission p = BasePermission.ADMINISTRATION; - -// Create or update the relevant ACL -MutableAcl acl = null; -try { - acl = (MutableAcl) aclService.readAclById(oi); -} catch (NotFoundException nfe) { - acl = aclService.createAcl(oi); -} - -// Now grant some permissions via an access control entry (ACE) -acl.insertAce(acl.getEntries().length, p, sid, true); -aclService.updateAcl(acl); - - In the example above, we're retrieving the ACL associated with the "Foo" domain object - with identifier number 44. We're then adding an ACE so that a principal named "Samantha" - can "administer" the object. The code fragment is relatively self-explanatory, except - the insertAce method. The first argument to the insertAce method is determining at what - position in the Acl the new entry will be inserted. In the example above, we're just - putting the new ACE at the end of the existing ACEs. The final argument is a boolean - indicating whether the ACE is granting or denying. Most of the time it will be granting - (true), but if it is denying (false), the permissions are effectively being - blocked. - Spring Security does not provide any special integration to automatically create, - update or delete ACLs as part of your DAO or repository operations. Instead, you will - need to write code like shown above for your individual domain objects. It's worth - considering using AOP on your services layer to automatically integrate the ACL - information with your services layer operations. We've found this quite an effective - approach in the past. - Once you've used the above techniques to store some ACL information in the database, - the next step is to actually use the ACL information as part of authorization decision - logic. You have a number of choices here. You could write your own - AccessDecisionVoter or - AfterInvocationProvider that respectively fires before or after a - method invocation. Such classes would use AclService to retrieve the - relevant ACL and then call Acl.isGranted(Permission[] permission, Sid[] sids, - boolean administrativeMode) to decide whether permission is granted or denied. - Alternately, you could use our AclEntryVoter, - AclEntryAfterInvocationProvider or - AclEntryAfterInvocationCollectionFilteringProvider classes. All of - these classes provide a declarative-based approach to evaluating ACL information at - runtime, freeing you from needing to write any code. Please refer to the sample - applications to learn how to use these classes. -
-
diff --git a/docs/manual/src/docbook/el-access.xml b/docs/manual/src/docbook/el-access.xml deleted file mode 100644 index 390f93d93a..0000000000 --- a/docs/manual/src/docbook/el-access.xml +++ /dev/null @@ -1,297 +0,0 @@ - - - Expression-Based Access Control - Spring Security 3.0 introduced the ability to use Spring EL expressions as an - authorization mechanism in addition to the simple use of configuration attributes and - access-decision voters which have seen before. Expression-based access control is built on - the same architecture but allows complicated boolean logic to be encapsulated in a single - expression. -
- Overview - Spring Security uses Spring EL for expression support and you should look at how that - works if you are interested in understanding the topic in more depth. Expressions are - evaluated with a root object as part of the evaluation context. Spring - Security uses specific classes for web and method security as the root object, in order - to provide built-in expressions and access to values such as the current - principal. -
- Common Built-In Expressions - The base class for expression root objects is - SecurityExpressionRoot. This provides some common expressions - which are available in both web and method security. - - Common built-in expressions - - - - - - Expression - Description - - - - - hasRole([role]) - Returns true if the current principal has the - specified role. - - - hasAnyRole([role1,role2]) - Returns true if the current principal has any - of the supplied roles (given as a comma-separated list of - strings) - - - principal - Allows direct access to the principal object representing the - current user - - - authentication - Allows direct access to the current - Authentication object obtained from - the SecurityContext - - - permitAll - Always evaluates to true - - - denyAll - Always evaluates to false - - - isAnonymous() - Returns true if the current principal is an - anonymous user - - - isRememberMe() - Returns true if the current principal is a - remember-me user - - - isAuthenticated() - Returns true if the user is not - anonymous - - - isFullyAuthenticated() - Returns true if the user is not an anonymous - or a remember-me user - - - -
-
-
-
- Web Security Expressions - To use expressions to secure individual URLs, you would first need to set the - use-expressions attribute in the <http> element - to true. Spring Security will then expect the - access attributes of the <intercept-url> - elements to contain Spring EL expressions. The expressions should evaluate to a boolean, - defining whether access should be allowed or not. For example: - - ... - -]]>Here we have defined that the admin area of an application - (defined by the URL pattern) should only be available to users who have the granted - authority admin and whose IP address matches a local subnet. We've - already seen the built-in hasRole expression in the previous section. - The expression hasIpAddress is an additional built-in expression - which is specific to web security. It is defined by the - WebSecurityExpressionRoot class, an instance of which is used as - the expression root object when evaluation web-access expressions. This object also - directly exposed the HttpServletRequest object under the - name request so you can invoke the request directly in an - expression. - If expressions are being used, a WebExpressionVoter will be - added to the AccessDecisionManager which is used by the - namespace. So if you aren't using the namespace and want to use expressions, you will - have to add one of these to your configuration. -
-
- Method Security Expressions - Method security is a bit more complicated than a simple allow or deny rule. Spring - Security 3.0 introduced some new annotations in order to allow comprehensive support for - the use of expressions. -
- <literal>@Pre</literal> and <literal>@Post</literal> Annotations - There are four annotations which support expression attributes to allow pre and - post-invocation authorization checks and also to support filtering of submitted - collection arguments or return values. They are @PreAuthorize, - @PreFilter, @PostAuthorize and - @PostFilter. Their use is enabled through the - global-method-security namespace - element:]]> -
- Access Control using <literal>@PreAuthorize</literal> and - <literal>@PostAuthorize</literal> - The most obviously useful annotation is @PreAuthorize which - decides whether a method can actually be invoked or not. For example (from the - Contacts sample - application) - @PreAuthorize("hasRole('ROLE_USER')") - public void create(Contact contact);which - means that access will only be allowed for users with the role "ROLE_USER". -
- Resolving method arguments - Obviously the same thing could easily be achieved using a traditional - configuration and a simple configuration attribute for the required role. But - what - about: - @PreAuthorize("hasPermission(#contact, 'admin')") - public void deletePermission(Contact contact, Sid recipient, Permission permission);Here - we're actually using a method argument as part of the expression to decide - whether the current user has the adminpermission for the given - contact. The built-in hasPermission() expression is linked - into the Spring Security ACL module through the application context, as we'll - see below. You can access any - of the method arguments by name as expression variables. - There are a number of ways in which Spring Security can resolve the method arguments. Spring Security - uses DefaultSecurityParameterNameDiscoverer to discover the parameter names. By default, - the following options are tried for a method as a whole. - - - If Spring Security's @P annotation is present on a single argument to the method, - the value will be used. This is useful for interfaces compiled with a JDK prior to JDK 8 which do not contain - any information about the parameter names. For example: -import org.springframework.security.access.method.P; - -... - -@PreAuthorize("#c.name == authentication.name") -public void doSomething(@P("c") Contact contact); - Behind the scenes this use implemented using AnnotationParameterNameDiscoverer which - can be customized to support the value attribute of any specified annotation. - - - If Spring Data's @Param annotation is present on at least one parameter for the method, - the value will be used. This is useful for interfaces compiled with a JDK prior to JDK 8 which do not contain - any information about the parameter names. For example: -import org.springframework.data.repository.query.Param; - -... - -@PreAuthorize("#n == authentication.name") -Contact findContactByName(@Param("n") String name); - Behind the scenes this use implemented using AnnotationParameterNameDiscoverer which - can be customized to support the value attribute of any specified annotation. - - - If JDK 8 was used to compile the source with the -parameters argument and Spring 4+ is being used, then - the standard JDK reflection API is used to discover the parameter names. This works on both classes and - interfaces. - - - Last, if the code was compiled with the debug symbols, the parameter names will be discovered using - the debug symbols. This will not work for interfaces since they do not have debug information about the - parameter names. For interfaces, annotations or the JDK 8 approach must be used. - - -
-
- Method Expressions and SpEL - Any Spring-EL functionality is available within - the expression, so you can also access properties on the arguments. For example, - if you wanted a particular method to only allow access to a user whose username - matched that of the contact, you could write - - @PreAuthorize("#contact.name == authentication.name") - public void doSomething(Contact contact); - Here we are accessing another built–in expression, authentication, - which is the Authentication stored in the - security context. You can also access its principal property - directly, using the expression principal. The value will - often be a UserDetails instance, so you might use an - expression like principal.username or - principal.enabled. -
-
- Accessing the return value - Less commonly, you may wish to perform an access-control check after the - method has been invoked. This can be achieved using the - @PostAuthorize annotation. To access the return value from a - method, use the built–in name returnObject in the - expression. -
-
-
- Filtering using <literal>@PreFilter</literal> and - <literal>@PostFilter</literal> - As you may already be aware, Spring Security supports filtering of collections - and arrays and this can now be achieved using expressions. This is most commonly - performed on the return value of a method. For - example: @PreAuthorize("hasRole('ROLE_USER')") - @PostFilter("hasPermission(filterObject, 'read') or hasPermission(filterObject, 'admin')") - public List<Contact> getAll();When - using the @PostFilter annotation, Spring Security iterates - through the returned collection and removes any elements for which the supplied - expression is false. The name filterObject refers to the - current object in the collection. You can also filter before the method call, - using @PreFilter, though this is a less common requirement. - The syntax is just the same, but if there is more than one argument which is a - collection type then you have to select one by name using the - filterTarget property of this annotation. - Note that filtering is obviously not a substitute for tuning your data - retrieval queries. If you are filtering large collections and removing many of - the entries then this is likely to be inefficient. -
-
-
- Built-In Expressions - There are some built-in expressions which are specific to method security, which - we have already seen in use above. The filterTarget and - returnValue values are simple enough, but the use of the - hasPermission() expression warrants a closer look. -
- The <interfacename>PermissionEvaluator</interfacename> interface - hasPermission() expressions are delegated to an instance of - PermissionEvaluator. It is intended to bridge - between the expression system and Spring Security's ACL system, allowing you to - specify authorization constraints on domain objects, based on abstract - permissions. It has no explicit dependencies on the ACL module, so you could - swap that out for an alternative implementation if required. The interface has - two methods: - - boolean hasPermission(Authentication authentication, Object targetDomainObject, - Object permission); - - boolean hasPermission(Authentication authentication, Serializable targetId, - String targetType, Object permission); -which - map directly to the available versions of the expression, with the exception - that the first argument (the Authentication - object) is not supplied. The first is used in situations where the domain - object, to which access is being controlled, is already loaded. Then expression - will return true if the current user has the given permission for that object. - The second version is used in cases where the object is not loaded, but its - identifier is known. An abstract type specifier for the domain - object is also required, allowing the correct ACL permissions to be loaded. This - has traditionally been the Java class of the object, but does not have to be as - long as it is consistent with how the permissions are loaded. - To use hasPermission() expressions, you have to explicitly - configure a PermissionEvaluator in your - application context. This would look something like this: - - - - - -]]>Where myPermissionEvaluator is the bean which - implements PermissionEvaluator. Usually this will - be the implementation from the ACL module which is called - AclPermissionEvaluator. See the Contacts - sample application configuration for more details. -
-
-
-
diff --git a/docs/manual/src/docbook/form-authentication.xml b/docs/manual/src/docbook/form-authentication.xml deleted file mode 100644 index 32840641a2..0000000000 --- a/docs/manual/src/docbook/form-authentication.xml +++ /dev/null @@ -1,68 +0,0 @@ - - - Form Authentication Mechanism - - -
- - Overview - - - HTTP Form Authentication involves using the - UsernamePasswordAuthenticationFilter to process a login form. This is - the most common way for an application to authenticate end users. Form-based - authentication is entirely compatible with the DAO, LDAP and JAAS authentication - providers. - This is also the mechanism used by the <form-login> element from the namespace - and it's recommended that you use that unless you have specific customization - requirements. -
- -
- - Configuration - - - The login form simply contains j_username and - j_password input fields, and posts to a URL that is monitored by the - filter (by default /j_spring_security_check). You should add an - UsernamePasswordAuthenticationFilter to your application context: - - - ]]> - - The configured AuthenticationManager processes each - authentication request. The destination following a successful authentication or an - authentication failure is controlled by the - AuthenticationSuccessHandler and - AuthenticationFailureHandler interfaces, respectively. - The filter has properties which allow you to set these - In versions prior to 3.0, the application flow at this point had evolved to a - stage was controlled by a mix of properties on this class and strategy plugins. The - decision was made for 3.0 to refactor the code to make these two strategies entirely - responsible. - . Some standard implementations are supplied for these such as - SimpleUrlAuthenticationSuccessHandler, - SavedRequestAwareAuthenticationSuccessHandler, - SimpleUrlAuthenticationFailureHandler and - ExceptionMappingAuthenticationFailureHandler. Have a look at the - Javadoc for these classes to see how they work. - - If authentication is successful, the resulting - Authentication object will be placed into the - SecurityContextHolder. The configured - AuthenticationSuccessHandler will then be called to either redirect or forward the user - to the appropriate destination. By default a - SavedRequestAwareAuthenticationSuccessHandler is used, which - means that the user will be redirected to the original destination they requested before - they were asked to login. - The ExceptionTranslationFilter caches the original request - a user makes. When the user authenticates, the request handler makes use of this - cached request to obtain the original URL and redirect to it. The original request - is then rebuilt and used as an alternative. - If authentication fails, the configured - AuthenticationFailureHandler will be invoked. -
-
diff --git a/docs/manual/src/docbook/headers.xml b/docs/manual/src/docbook/headers.xml deleted file mode 100644 index d2f9c55b85..0000000000 --- a/docs/manual/src/docbook/headers.xml +++ /dev/null @@ -1,436 +0,0 @@ - - - Security Headers - - This section discusses Spring Security's support for adding various security headers to the response. -
- Default Security Headers - Spring Security allows users to easily inject the default security headers to assist in protecting their - application. The following is a list of the current Default Security Headers provided - by Spring Security: - - - Cache Control - - - Content Type Options - - - HTTP Strict Transport Security - - - X-Frame-Options - - - X-XSS-Protection - - - While each of these headers are considered best practice, it should be noted that not all clients - utilize the headers, so additional testing is encouraged. For passivity reasons, if you are using Spring Security's - XML namespace support, you must explicitly enable the security headers. All of the default headers can be easily added - using the <headers> element with no child elements: - - SEC-2348 is logged to ensure Spring - Security 4.x's XML namespace configuration will enable Security headers by default. - - - - - -]]> - Alternatively, you can choose to explicitly list the headers you wish to include. For example, the following is - the same the previous configuration. Removing any of the elements will remove that header from the responses. - - - - - - - - - - -]]> - If you are using Spring Security's Java configuration, all of the default security headers are added by default. - They can be disabled using the Java configuration below: - - As soon as you specify any headers that should be included, then only those headers will be include. For example, the - following configuration will include support for Cache Control and - X-Frame-Options only. - -
- Cache Control - In the past Spring Security required you to provide your own cache control for your web application. This - seemed reasonable at the time, but browser caches have evolved to include caches for secure connections as - well. This means that a user may view an authenticated page, log out, and then a malicious user can use the - browser history to view the cached page. To help mitigate this Spring Security has added cache control support - which will insert the following headers into you response. - - Simply adding the <headers> element with no child elements will - automatically add Cache Control and quite a few other protections. However, if you only want cache control, you can - enable this feature using Spring Security's XML namespace with the - <cache-control> element. - - - - - - -]]> - Similarly, you can enable only cache control within Java Configuration with the following: - - If you actually want to cache specific responses, your application can selectively invoke - HttpServletResponse.setHeader(String,String) - to override the header set by Spring Security. This is useful to ensure things - like CSS, JavaScript, and images are properly cached. - When using Spring Web MVC, this is typically done within your configuration. For example, the following configuration will - ensure that the cache headers are set for all of your resources: - -
-
- Content Type Options - Historically browsers, including Internet Explorer, would try to guess the content type of a request using - content sniffing. This - allowed browsers to improve the user experience by guessing the content type on resources that had not specified the content type. - For example, if a browser encountered a JavaScript file that did not have the content type specified, it would be able to guess the content - type and then execute it. - - There are many additional things one should do (i.e. only display the document in a distinct domain, ensure - Content-Type header is set, sanitize the document, etc) when allowing content to be uploaded. However, these measures - are out of the scope of what Spring Security provides. It is also important to point out when disabling content sniffing, - you must specify the content type in order for things to work properly. - - The problem with content sniffing is that this allowed malicious users to use polyglots (i.e. a file that is valid as multiple content - types) to execute XSS attacks. For example, some sites may allow users to submit a valid postscript document to a website and view it. A malicious - user might create a postscript document that is also a valid - JavaScript file and execute a XSS attack with it. - Content sniffing can be disabled by adding the following header to our response: - - Just as with the cache control element, the nosniff directive is added by default when using the <headers> element with no child elements. - However, if you want more control over which headers are added you can use the - <content-type-options> element as shown below: - - - - - - -]]> - The X-Content-Type-Options header is added by default with Spring Security Java configuration. If you want more control over the headers, you can - explicitly specify the content type options with the following: - -
-
- HTTP Strict Transport Security (HSTS) - When you type in your bank's website, do you enter mybank.example.com or do you enter https://mybank.example.com? If you - omit the https protocol, you are potentially vulnerable to - Man in the Middle attacks. Even if the website performs a redirect - to https://mybank.example.com a malicious user could intercept the initial HTTP request and manipulate the response (i.e. - redirect to https://mibank.example.com and steal their credentials). - Many users omit the https protocol and this is why HTTP Strict Transport Security (HSTS) - was created. Once mybank.example.com is added as a HSTS host, a browser can - know ahead of time that any request to mybank.example.com should be interpreted as - https://mybank.example.com. This greatly reduces the possibility of a Man in the Middle attack occurring. - - In accordance with RFC6797, the HSTS header is only injected into HTTPS - responses. In order for the browser to acknowledge the header, the browser must first trust the CA that signed the SSL certificate used to make the - connection (not just the SSL certificate). - - One way for a site to be marked as a HSTS host is to have the host preloaded into the browser. Another is to add the - "Strict-Transport-Security" header to the response. For example the following would instruct the browser to treat the domain as an HSTS - host for a year (there are approximately 31536000 seconds in a year): - - The optional includeSubDomains directive instructs Spring Security that subdomains (i.e. secure.mybank.example.com) should also be - treated as an HSTS domain. - As with the other headers, Spring Security adds the previous header to the response when the <headers> element is specified with - no child elements. It is also automatically added when you are using Java Configuration. You can also only use HSTS headers with the - <hsts> element as shown below: - - - - - - -]]> - Similarly, you can enable only HSTS headers with Java Configuration: - -
-
- X-Frame-Options - Allowing your website to be added to a frame can be a security issue. For example, using clever CSS styling users - could be tricked into clicking on something that they were not intending ( - video demo). For example, a user that is logged - into their bank might click a button that grants access to other users. This sort of attack is known as - Clickjacking. - - Another modern approach to dealing with clickjacking is using a Content - Security Policy. Spring Security does not provide - support for this as the specification is not released and it is quite a bit more complicated. However, you could use the - static headers feature to implement this. To stay up to date with this - issue and to see how you can implement it with Spring Security refer to - SEC-2117 - - There are a number ways to mitigate clickjacking attacks. For example, to protect legacy browsers from clickjacking attacks you - can use - frame - breaking code. While not perfect, the frame breaking code is the best you can do for the legacy browsers. - A more modern approach to address clickjacking is to use - X-Frame-Options header: - - The X-Frame-Options response header instructs the browser to prevent any site with this header in the response from being rendered - within a frame. As with the other response headers, this is automatically included when the <headers> element is specified with no - child elements. You can also explicitly specify the frame-options element to control which headers - are added to the response. - - - - - - -]]> - Similarly, you can enable only frame options within Java Configuration with the following: - - If you want to change the value for the X-Frame-Options header, then you can use a - XFrameOptionsHeaderWriter instance. -
-
- X-XSS-Protection - Some browsers have built in support for filtering out - reflected - XSS attacks. This is by no means full proof, but does assist in XSS protection. - The filtering is typically enabled by default, so adding the header typically just ensures it is enabled and - instructs the browser what to do when a XSS attack is detected. For example, the filter might try to change the - content in the least invasive way to still render everything. At times, this type of replacement can become a - XSS - vulnerability in itself. Instead, it is best to block the content rather than attempt to fix it. To do this we can - add the following header: - - This header is included by default when the <headers> element is specified with no child elements. We can explicitly - state it using the xss-protection element as shown below: - - - - - - -]]> - Similarly, you can enable only xss protection within Java Configuration with the following: - -
-
-
- Custom Headers - Spring Security has mechanisms to make it convenient to add the more common security headers to your application. However, it also provides - hooks to enable adding custom headers. -
- Static Headers - There may be times you wish to inject custom security headers into your application that are not supported out of the box. For example, perhaps - you wish to have early support for Content Security Policy in order to ensure that resources - are only loaded from the same origin. Since support for Content Security Policy has not been finalized, browsers use one of two common extension headers - to implement the feature. This means we will need to inject the policy twice. An example of the headers can be seen below: - - When using the XML namespace, these headers can be added to the response using the <header> element as - shown below: - - - - -
-
- - ]]> - Similarly, the headers could be added to the response using Java Configuration as shown in the following: - -
-
- Headers Writer - When the namespace or Java configuration does not support the headers you want, you can create a custom HeadersWriter instance - or even provide a custom implementation of the HeadersWriter. - Let's take a look at an example of using an custom instance of XFrameOptionsHeaderWriter. Perhaps you want to allow framing of content - for the same origin. This is easily supported by setting the policy - attribute to "SAMEORIGIN", but let's take a look at a more explicit example using the ref attribute. - - - - -
- - - -]]> - - We could also restrict framing of content to the same origin with Java configuration: - -
-
- DelegatingRequestMatcherHeaderWriter - At times you may want to only write a header for certain requests. For example, perhaps you want to only protect your log in page from being framed. You could use the - DelegatingRequestMatcherHeaderWriter to do so. When using the XML namespace configuration, this can be done with the following: - - - - -
- - - - - - - - - - -]]> - We could also prevent framing of content to the log in page using java configuration: - -
-
-
diff --git a/docs/manual/src/docbook/html-titlepage.xml b/docs/manual/src/docbook/html-titlepage.xml deleted file mode 100644 index ee79a7d1a9..0000000000 --- a/docs/manual/src/docbook/html-titlepage.xml +++ /dev/null @@ -1,61 +0,0 @@ - - - - - - - - - - - - <subtitle/> - <corpauthor/> - <authorgroup/> - <author/> - <mediaobject/> - <othercredit/> - <productname/> - <releaseinfo/> - <copyright/> - <pubdate/> - <revision/> - <revhistory/> - <abstract/> - </t:titlepage-content> - - <t:titlepage-content t:side="verso"> - <legalnotice/> - </t:titlepage-content> - - <t:titlepage-separator> - <hr/> - </t:titlepage-separator> - - <t:titlepage-before t:side="recto"> - </t:titlepage-before> - - <t:titlepage-before t:side="verso"> - </t:titlepage-before> -</t:titlepage> - -</t:templates> diff --git a/docs/manual/src/docbook/index-classes.xsl b/docs/manual/src/docbook/index-classes.xsl deleted file mode 100644 index 37d4235109..0000000000 --- a/docs/manual/src/docbook/index-classes.xsl +++ /dev/null @@ -1,19 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> - -<xsl:stylesheet - xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0" xmlns:db="http://docbook.org/ns/docbook"> - <xsl:output method="text"/> - - <xsl:template match="db:interfacename|db:classname"> - <xsl:variable name="classname" select="."/> - <xsl:for-each select="ancestor::*[@xml:id][1]"> - <xsl:variable name="title" select="db:info/db:title|db:title"/> - <xsl:value-of select="concat($classname, ':', @xml:id, ':', $title,';')"/> - </xsl:for-each> - </xsl:template> - - <xsl:template match="text()|@*|*"> - <xsl:apply-templates/> - </xsl:template> - -</xsl:stylesheet> \ No newline at end of file diff --git a/docs/manual/src/docbook/index.xml b/docs/manual/src/docbook/index.xml deleted file mode 100644 index 191ee1405a..0000000000 --- a/docs/manual/src/docbook/index.xml +++ /dev/null @@ -1,181 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<book version="5.0" xml:id="spring-security-reference-guide" xmlns="http://docbook.org/ns/docbook" - xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xi="http://www.w3.org/2001/XInclude"> - <info> - <title>Spring Security - Reference Documentation - - - Ben Alex - - - Luke Taylor - - - Spring Security - ${version} - - - - Preface - - Spring Security provides a comprehensive security solution for J2EE-based enterprise - software applications. As you will discover as you venture through this reference guide, - we have tried to provide you a useful and highly configurable security system. - Security is an ever-moving target, and it's important to pursue a comprehensive, - system-wide approach. In security circles we encourage you to adopt "layers of - security", so that each layer tries to be as secure as possible in its own right, with - successive layers providing additional security. The "tighter" the security of each - layer, the more robust and safe your application will be. At the bottom level you'll - need to deal with issues such as transport security and system identification, in order - to mitigate man-in-the-middle attacks. Next you'll generally utilise firewalls, perhaps - with VPNs or IP security to ensure only authorised systems can attempt to connect. In - corporate environments you may deploy a DMZ to separate public-facing servers from - backend database and application servers. Your operating system will also play a - critical part, addressing issues such as running processes as non-privileged users and - maximising file system security. An operating system will usually also be configured - with its own firewall. Hopefully somewhere along the way you'll be trying to prevent - denial of service and brute force attacks against the system. An intrusion detection - system will also be especially useful for monitoring and responding to attacks, with - such systems able to take protective action such as blocking offending TCP/IP addresses - in real-time. Moving to the higher layers, your Java Virtual Machine will hopefully be - configured to minimize the permissions granted to different Java types, and then your - application will add its own problem domain-specific security configuration. Spring - Security makes this latter area - application security - much easier. - Of course, you will need to properly address all security layers mentioned above, - together with managerial factors that encompass every layer. A non-exhaustive list of - such managerial factors would include security bulletin monitoring, patching, personnel - vetting, audits, change control, engineering management systems, data backup, disaster - recovery, performance benchmarking, load monitoring, centralised logging, incident - response procedures etc. - With Spring Security being focused on helping you with the enterprise application - security layer, you will find that there are as many different requirements as there are - business problem domains. A banking application has different needs from an ecommerce - application. An ecommerce application has different needs from a corporate sales force - automation tool. These custom requirements make application security interesting, - challenging and rewarding. - Please read , in its entirety to begin with. This - will introduce you to the framework and the namespace-based configuration system with - which you can get up and running quite quickly. To get more of an understanding of how - Spring Security works, and some of the classes you might need to use, you should then - read . The remaining parts of this guide are - structured in a more traditional reference style, designed to be read on an as-required - basis. We'd also recommend that you read up as much as possible on application security - issues in general. Spring Security is not a panacea which will solve all security - issues. It is important that the application is designed with security in mind from the - start. Attempting to retrofit it is not a good idea. In particular, if you are building - a web application, you should be aware of the many potential vulnerabilities such as - cross-site scripting, request-forgery and session-hijacking which you should be taking - into account from the start. The OWASP web site (http://www.owasp.org/) maintains a top - ten list of web application vulnerabilities as well as a lot of useful reference - information. - We hope that you find this reference guide useful, and we welcome your feedback and - suggestions. - Finally, welcome to the Spring Security community. - - - - Getting Started - - The later parts of this guide provide an in-depth discussion of the framework - architecture and implementation classes, which you need to understand if you want to - do any serious customization. In this part, we'll introduce Spring Security 3.0, - give a brief overview of the project's history and take a slightly gentler look at - how to get started using the framework. In particular, we'll look at namespace - configuration which provides a much simpler way of securing your application - compared to the traditional Spring bean approach where you have to wire up all the - implementation classes individually. - We'll also take a look at the sample applications that are available. It's worth - trying to run these and experimenting with them a bit even before you read the later - sections - you can dip back into them as your understanding of the framework - increases. Please also check out the project website as it has useful information on building the project, - plus links to articles, videos and tutorials. - - - - - - - - - Architecture and Implementation - - Once you are familiar with setting up and running some namespace-configuration - based applications, you may wish to develop more of an understanding of how the - framework actually works behind the namespace facade. Like most software, Spring - Security has certain central interfaces, classes and conceptual abstractions that - are commonly used throughout the framework. In this part of the reference guide we - will look at some of these and see how they work together to support authentication - and access-control within Spring Security. - - - - - - Web Application Security - - Most Spring Security users will be using the framework in applications which make - user of HTTP and the Servlet API. In this part, we'll take a look at how Spring - Security provides authentication and access-control features for the web layer of an - application. We'll look behind the facade of the namespace and see which classes and - interfaces are actually assembled to provide web-layer security. In some situations - it is necessary to use traditional bean configuration to provide full control over - the configuration, so we'll also see how to configure these classes directly without - the namespace. - - - - - - - - - - - - - - Authorization - - The advanced authorization capabilities within Spring Security represent one of - the most compelling reasons for its popularity. Irrespective of how you choose to - authenticate - whether using a Spring Security-provided mechanism and provider, or - integrating with a container or other non-Spring Security authentication authority - - you will find the authorization services can be used within your application in a - consistent and simple way. - In this part we'll explore the different - AbstractSecurityInterceptor implementations, which were - introduced in Part I. We then move on to explore how to fine-tune authorization - through use of domain access control lists. - - - - - - - Additional Topics - - - In this part we cover features which require a knowledge of previous chapters as - well as some of the more advanced and less-commonly used features of the - framework. - - - - - - - - - - - - - - - diff --git a/docs/manual/src/docbook/introduction.xml b/docs/manual/src/docbook/introduction.xml deleted file mode 100644 index 0e422b1649..0000000000 --- a/docs/manual/src/docbook/introduction.xml +++ /dev/null @@ -1,308 +0,0 @@ - - - Introduction -
- What is Spring Security? - Spring Security provides comprehensive security services for J2EE-based enterprise - software applications. There is a particular emphasis on supporting projects built using - The Spring Framework, which is the leading J2EE solution for enterprise software - development. If you're not using Spring for developing enterprise applications, we - warmly encourage you to take a closer look at it. Some familiarity with Spring - and in - particular dependency injection principles - will help you get up to speed with Spring - Security more easily. - People use Spring Security for many reasons, but most are drawn to the project after - finding the security features of J2EE's Servlet Specification or EJB Specification lack - the depth required for typical enterprise application scenarios. Whilst mentioning these - standards, it's important to recognise that they are not portable at a WAR or EAR level. - Therefore, if you switch server environments, it is typically a lot of work to - reconfigure your application's security in the new target environment. Using Spring - Security overcomes these problems, and also brings you dozens of other useful, - customisable security features. - As you probably know two major areas of application security are - authentication and authorization (or - access-control). These are the two main areas that Spring Security - targets. Authentication is the process of establishing a principal is who - they claim to be (a principal generally means a user, device or some - other system which can perform an action in your application). - Authorization refers to the process of deciding whether a principal is - allowed to perform an action within your application. To arrive at the point where an - authorization decision is needed, the identity of the principal has already been - established by the authentication process. These concepts are common, and not at all - specific to Spring Security. - At an authentication level, Spring Security supports a wide range of authentication - models. Most of these authentication models are either provided by third parties, or are - developed by relevant standards bodies such as the Internet Engineering Task Force. In - addition, Spring Security provides its own set of authentication features. Specifically, - Spring Security currently supports authentication integration with all of these - technologies: - - - HTTP BASIC authentication headers (an IETF RFC-based standard) - - - HTTP Digest authentication headers (an IETF RFC-based standard) - - - HTTP X.509 client certificate exchange (an IETF RFC-based standard) - - - LDAP (a very common approach to cross-platform authentication needs, - especially in large environments) - - - Form-based authentication (for simple user interface needs) - - - OpenID authentication - - - Authentication based on pre-established request headers (such as Computer - Associates Siteminder) - - - JA-SIG Central Authentication Service (otherwise known as CAS, which is a - popular open source single sign-on system) - - - Transparent authentication context propagation for Remote Method Invocation - (RMI) and HttpInvoker (a Spring remoting protocol) - - - Automatic "remember-me" authentication (so you can tick a box to avoid - re-authentication for a predetermined period of time) - - - Anonymous authentication (allowing every unauthenticated call to automatically assume a - particular security identity) - - - Run-as authentication (which is useful if one call should proceed with a - different security identity) - - - Java Authentication and Authorization Service (JAAS) - - - JEE container autentication (so you can still use Container Managed - Authentication if desired) - - - Kerberos - - - Java Open Source Single Sign On (JOSSO) * - - - OpenNMS Network Management Platform * - - - AppFuse * - - - AndroMDA * - - - Mule ESB * - - - Direct Web Request (DWR) * - - - Grails * - - - Tapestry * - - - JTrac * - - - Jasypt * - - - Roller * - - - Elastic Path * - - - Atlassian Crowd * - - - Your own authentication systems (see below) - - - (* Denotes provided by a third party - - Many independent software vendors (ISVs) adopt Spring Security because of this - significant choice of flexible authentication models. Doing so allows them to quickly - integrate their solutions with whatever their end clients need, without undertaking a - lot of engineering or requiring the client to change their environment. If none of the - above authentication mechanisms suit your needs, Spring Security is an open platform and - it is quite simple to write your own authentication mechanism. Many corporate users of - Spring Security need to integrate with "legacy" systems that don't follow any particular - security standards, and Spring Security is happy to "play nicely" with such - systems. - Irrespective of the authentication mechanism, Spring Security provides a deep set - of authorization capabilities. There are three main areas of interest - - authorizing web requests, authorizing whether methods can be - invoked, and authorizing access to individual domain object instances. To help you - understand the differences, consider the authorization capabilities found in the Servlet - Specification web pattern security, EJB Container Managed Security and file system - security respectively. Spring Security provides deep capabilities in all of these - important areas, which we'll explore later in this reference guide. -
-
- History - Spring Security began in late 2003 as The Acegi Security System for - Spring. A question was posed on the Spring Developers' mailing list asking - whether there had been any consideration given to a Spring-based security - implementation. At the time the Spring community was relatively small (especially - compared with the size today!), and indeed Spring itself had only existed as a - SourceForge project from early 2003. The response to the question was that it was a - worthwhile area, although a lack of time currently prevented its exploration. - With that in mind, a simple security implementation was built and not released. A few - weeks later another member of the Spring community inquired about security, and at the - time this code was offered to them. Several other requests followed, and by January 2004 - around twenty people were using the code. These pioneering users were joined by others - who suggested a SourceForge project was in order, which was duly established in March - 2004. - In those early days, the project didn't have any of its own authentication modules. - Container Managed Security was relied upon for the authentication process, with Acegi - Security instead focusing on authorization. This was suitable at first, but as more and - more users requested additional container support, the fundamental limitation of - container-specific authentication realm interfaces became clear. There was also a - related issue of adding new JARs to the container's classpath, which was a common source - of end user confusion and misconfiguration. - Acegi Security-specific authentication services were subsequently introduced. Around a - year later, Acegi Security became an official Spring Framework subproject. The 1.0.0 - final release was published in May 2006 - after more than two and a half years of active - use in numerous production software projects and many hundreds of improvements and - community contributions. - Acegi Security became an official Spring Portfolio project towards the end of 2007 and - was rebranded as Spring Security. - Today Spring Security enjoys a strong and active open source community. There are - thousands of messages about Spring Security on the support forums. There is an active - core of developers who work on the code itself and an active community which also - regularly share patches and support their peers. -
-
- Release Numbering - It is useful to understand how Spring Security release numbers work, as it will help - you identify the effort (or lack thereof) involved in migrating to future releases of - the project. Each release uses a standard triplet of integers: MAJOR.MINOR.PATCH. The - intent is that MAJOR versions are incompatible, large-scale upgrades of the API. MINOR - versions should largely retain source and binary compatibility with older minor - versions, thought there may be some design changes and incompatible udates. PATCH level - should be perfectly compatible, forwards and backwards, with the possible exception of - changes which are to fix bugs and defects. - The extent to which you are affected by changes will depend on how tightly integrated - your code is. If you are doing a lot of customization you are more likely to be affected - than if you are using a simple namespace configuration. - You should always test your application thoroughly before rolling out a new - version. -
-
- Getting Spring Security - You can get hold of Spring Security in several ways. You can download a packaged - distribution from the main Spring download page, download individual jars (and sample WAR files) from the Maven - Central repository (or a SpringSource Maven repository for snapshot and milestone - releases) or, alternatively, you can build the project from source yourself. See the - project web site for more details. -
- Project Modules - In Spring Security 3.0, the codebase has been sub-divided into separate jars which - more clearly separate different functionaltiy areas and third-party dependencies. If - you are using Maven to build your project, then these are the modules you will add - to your pom.xml. Even if you're not using Maven, we'd recommend - that you consult the pom.xml files to get an idea of - third-party dependencies and versions. Alternatively, a good idea is to examine the - libraries that are included in the sample applications. -
- Core - <literal>spring-security-core.jar</literal> - Contains core authentication and access-contol classes and interfaces, - remoting support and basic provisioning APIs. Required by any application which - uses Spring Security. Supports standalone applications, remote clients, method - (service layer) security and JDBC user provisioning. Contains the top-level packages: - - org.springframework.security.core - - - org.springframework.security.access - - - org.springframework.security.authentication - - - org.springframework.security.provisioning - - -
-
- Remoting - <literal>spring-security-remoting.jar</literal> - Provides intergration with Spring Remoting. You don't need this unless you are - writing a remote client which uses Spring Remoting. The main package is - org.springframework.security.remoting. -
-
- Web - <literal>spring-security-web.jar</literal> - Contains filters and related web-security infrastructure code. Anything with a - servlet API dependency. You'll need it if you require Spring Security web - authentication services and URL-based access-control. The main package is - org.springframework.security.web. -
-
- Config - <literal>spring-security-config.jar</literal> - Contains the security namespace parsing code. You need it if you are using the - Spring Security XML namespace for configuration. The main package is - org.springframework.security.config. None of the - classes are intended for direct use in an application. -
-
- LDAP - <literal>spring-security-ldap.jar</literal> - LDAP authentication and provisioning code. Required if you need to use LDAP - authentication or manage LDAP user entries. The top-level package is - org.springframework.security.ldap. -
-
- ACL - <literal>spring-security-acl.jar</literal> - Specialized domain object ACL implementation. Used to apply security to - specific domain object instances within your application. The top-level package - is org.springframework.security.acls. -
-
- CAS - <literal>spring-security-cas.jar</literal> - Spring Security's CAS client integration. If you want to use Spring Security - web authentication with a CAS single sign-on server. The top-level package is - org.springframework.security.cas. -
-
- OpenID - <literal>spring-security-openid.jar</literal> - OpenID web authentication support. Used to authenticate users against an - external OpenID server. org.springframework.security.openid. - Requires OpenID4Java. -
-
-
- Checking out the Source - Since Spring Security is an Open Source project, we'd strongly encourage you to - check out the source code using git. This will give you full access to all the - sample applications and you can build the most up to date version of the project - easily. Having the source for a project is also a huge help in debugging. Exception - stack traces are no longer obscure black-box issues but you can get straight to the - line that's causing the problem and work out what's happening. The source is the - ultimate documentation for a project and often the simplest place to find out how - something actually works. - To obtain the source for the project, use the following git command: - - git clone git://git.springsource.org/spring-security/spring-security.git - - - This will give you access to the entire project history (including all releases - and branches) on your local machine. -
-
-
diff --git a/docs/manual/src/docbook/jaas-auth-provider.xml b/docs/manual/src/docbook/jaas-auth-provider.xml deleted file mode 100644 index 91d49de2da..0000000000 --- a/docs/manual/src/docbook/jaas-auth-provider.xml +++ /dev/null @@ -1,232 +0,0 @@ - - - Java Authentication and Authorization Service (JAAS) Provider - - -
- - Overview - - Spring Security provides a package able to delegate authentication requests to the - Java Authentication and Authorization Service (JAAS). This package is discussed in - detail below. -
- -
- - AbstractJaasAuthenticationProvider - - The AbstractJaasAuthenticationProvider is the basis for the - provided JAAS AuthenticationProvider implementations. Subclasses - must implement a method that creates the LoginContext. The - AbstractJaasAuthenticationProvider has a number of dependencies that can - be injected into it that are discussed below. - -
- - JAAS CallbackHandler - - - Most JAAS LoginModules require a callback of some sort. These - callbacks are usually used to obtain the username and password from the user. - - In a Spring Security deployment, Spring Security is responsible for this user - interaction (via the authentication mechanism). Thus, by the time the authentication - request is delegated through to JAAS, Spring Security's authentication mechanism - will already have fully-populated an Authentication - object containing all the information required by the JAAS - LoginModule. - - Therefore, the JAAS package for Spring Security provides two default callback - handlers, JaasNameCallbackHandler and - JaasPasswordCallbackHandler. Each of these callback handlers - implement JaasAuthenticationCallbackHandler. In most cases these - callback handlers can simply be used without understanding the internal - mechanics. - - For those needing full control over the callback behavior, internally - AbstractJaasAuthenticationProvider wraps these - JaasAuthenticationCallbackHandlers with an - InternalCallbackHandler. The - InternalCallbackHandler is the class that actually implements - JAAS’ normal CallbackHandler interface. Any time that the JAAS - LoginModule is used, it is passed a list of application context - configured InternalCallbackHandlers. If the - LoginModule requests a callback against the - InternalCallbackHandlers, the callback is in-turn passed to the - JaasAuthenticationCallbackHandlers being wrapped. -
- -
- - JAAS AuthorityGranter - - - JAAS works with principals. Even "roles" are represented as principals in JAAS. - Spring Security, on the other hand, works with - Authentication objects. Each - Authentication object contains a single principal, - and multiple GrantedAuthoritys. To facilitate - mapping between these different concepts, Spring Security's JAAS package includes an - AuthorityGranter interface. - - An AuthorityGranter is responsible for inspecting a JAAS - principal and returning a set of Strings, representing the - authorities assigned to the principal. For each returned authority string, the - AbstractJaasAuthenticationProvider creates a - JaasGrantedAuthority (which implements Spring Security’s - GrantedAuthority interface) containing the authority - string and the JAAS principal that the - AuthorityGranter was passed. The - AbstractJaasAuthenticationProvider obtains the JAAS principals by - firstly successfully authenticating the user’s credentials using the JAAS - LoginModule, and then accessing the - LoginContext it returns. A call to - LoginContext.getSubject().getPrincipals() is made, with each - resulting principal passed to each AuthorityGranter - defined against the - AbstractJaasAuthenticationProvider.setAuthorityGranters(List) - property. - - Spring Security does not include any production - AuthorityGranters given that every JAAS principal has - an implementation-specific meaning. However, there is a - TestAuthorityGranter in the unit tests that demonstrates a simple - AuthorityGranter implementation. -
-
-
- - DefaultJaasAuthenticationProvider - - The DefaultJaasAuthenticationProvider allows a JAAS - Configuration object to be injected into it as a dependency. It then - creates a LoginContext using the injected JAAS Configuration. - This means that DefaultJaasAuthenticationProvider is not bound any particular implementation - of Configuration as JaasAuthenticationProvider is. - -
- - InMemoryConfiguration - - In order to make it easy to inject a Configuration into - DefaultJaasAuthenticationProvider, a default in memory - implementation named InMemoryConfiguration is provided. The - implementation constructor accepts a Map where each key represents a - login configuration name and the value represents an Array of - AppConfigurationEntrys. - InMemoryConfiguration also supports a default - Array of AppConfigurationEntry objects that - will be used if no mapping is found within the provided Map. For - details, refer to the class level javadoc of InMemoryConfiguration. -
- -
- - DefaultJaasAuthenticationProvider Example Configuration - - While the Spring configuration for InMemoryConfiguration can be - more verbose than the standarad JAAS configuration files, using it in conjuction with - DefaultJaasAuthenticationProvider is more flexible than - JaasAuthenticationProvider since it not dependant on the default - Configuration implementation. - An example configuration of DefaultJaasAuthenticationProvider using - InMemoryConfiguration is provided below. Note that custom implementations of - Configuration can easily be injected into - DefaultJaasAuthenticationProvider as well. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -]]> -
-
- -
- - JaasAuthenticationProvider - - The JaasAuthenticationProvider assumes the default Configuration is an instance of - - ConfigFile. This assumption is made in order to attempt to update the Configuration. The - JaasAuthenticationProvider then uses the default Configuration to create the - LoginContext. - - Let’s assume we have a JAAS login configuration file, - /WEB-INF/login.conf, with the following contents: - -JAASTest { - sample.SampleLoginModule required; -}; - Like all Spring Security beans, the JaasAuthenticationProvider - is configured via the application context. The following definitions would correspond to - the above JAAS login configuration file: - - - - - - - - - - - - - - -]]> -
-
- - Running as a Subject - - If configured, the JaasApiIntegrationFilter will attempt to - run as the Subject on the - JaasAuthenticationToken. This means that the - Subject can be accessed using: - - This integration can easily be configured using the - jaas-api-provision attribute. This - feature is useful when integrating with legacy or external API's that rely on the - JAAS Subject being populated. -
-
\ No newline at end of file diff --git a/docs/manual/src/docbook/ldap-auth-provider.xml b/docs/manual/src/docbook/ldap-auth-provider.xml deleted file mode 100644 index 63bb022969..0000000000 --- a/docs/manual/src/docbook/ldap-auth-provider.xml +++ /dev/null @@ -1,432 +0,0 @@ - - - LDAP Authentication - -
- - Overview - - LDAP is often used by organizations as a central repository for user information and - as an authentication service. It can also be used to store the role information for - application users. - There are many different scenarios for how an LDAP server may be configured so Spring - Security's LDAP provider is fully configurable. It uses separate strategy interfaces for - authentication and role retrieval and provides default implementations which can be - configured to handle a wide range of situations. - You should be familiar with LDAP before trying to use it with Spring Security. The - following link provides a good introduction to the concepts involved and a guide to - setting up a directory using the free LDAP server OpenLDAP: http://www.zytrax.com/books/ldap/. - Some familiarity with the JNDI APIs used to access LDAP from Java may also be useful. We - don't use any third-party LDAP libraries (Mozilla, JLDAP etc.) in the LDAP provider, but - extensive use is made of Spring LDAP, so some familiarity with that project may be - useful if you plan on adding your own customizations. - When using LDAP authentication, it is important to ensure that you configure LDAP connection - pooling properly. If you are unfamiliar with how to do this, you can refer to the - Java LDAP - documentation. -
-
- - Using LDAP with Spring Security - - LDAP authentication in Spring Security can be roughly divided into the following - stages. - - Obtaining the unique LDAP Distinguished Name, or DN, from the - login name. This will often mean performing a search in the directory, unless - the exact mapping of usernames to DNs is known in advance. So a user might enter - the name joe when logging in, but the actual name used to - authenticate to LDAP will be the full DN, such as - uid=joe,ou=users,dc=springsource,dc=com. - - - Authenticating the user, either by binding as that user or by - performing a remote compare operation of the user's password - against the password attribute in the directory entry for the DN. - - - Loading the list of authorities for the user. - - The exception is when the LDAP directory is just being used to retrieve - user information and authenticate against it locally. This may not be possible as - directories are often set up with limited read access for attributes such as user - passwords. - We will look at some configuration scenarios below. For full information on available - configuration options, please consult the security namespace schema (information from - which should be available in your XML editor). -
-
- - Configuring an LDAP Server - - The first thing you need to do is configure the server against which authentication - should take place. This is done using the <ldap-server> element - from the security namespace. This can be configured to point at an external LDAP server, - using the url attribute: -]]> - -
- - Using an Embedded Test Server - - The <ldap-server> element can also be used to create an - embedded server, which can be very useful for testing and demonstrations. In this - case you use it without the url attribute: - ]]> - Here we've specified that the root DIT of the directory should be - dc=springframework,dc=org, which is the default. Used this way, the - namespace parser will create an embedded Apache Directory server and scan the - classpath for any LDIF files, which it will attempt to load into the server. You can - customize this behaviour using the ldif attribute, which defines - an LDIF resource to be loaded: - ]]> This makes it a lot easier to get up and running with LDAP, since it - can be inconvenient to work all the time with an external server. It also insulates - the user from the complex bean configuration needed to wire up an Apache Directory - server. Using plain Spring Beans the configuration would be much more cluttered. You - must have the necessary Apache Directory dependency jars available for your - application to use. These can be obtained from the LDAP sample application. -
-
- - Using Bind Authentication - - This is the most common LDAP authentication scenario. - ]]> This simple example would obtain the DN for the user by - substituting the user login name in the supplied pattern and attempting to bind as - that user with the login password. This is OK if all your users are stored under a - single node in the directory. If instead you wished to configure an LDAP search - filter to locate the user, you could use the following: - ]]> If used with the server definition above, this would - perform a search under the DN ou=people,dc=springframework,dc=org - using the value of the user-search-filter attribute as a filter. - Again the user login name is substituted for the parameter in the filter name, so it - will search for an entry with the uid attribute equal to the user - name. If user-search-base isn't supplied, the search will be - performed from the root. -
-
- - Loading Authorities - - How authorities are loaded from groups in the LDAP directory is controlled by the - following attributes. - - group-search-base. Defines the part of the directory - tree under which group searches should be performed. - - - group-role-attribute. The attribute which contains the - name of the authority defined by the group entry. Defaults to - cn - - - group-search-filter. The filter which is used to - search for group membership. The default is - uniqueMember={0}, corresponding to the - groupOfUniqueNames LDAP class - Note that this is different from the default configuration of the - underlying DefaultLdapAuthoritiesPopulator - which uses member={0}. - . - In this case, the substituted parameter is the full distinguished name - of the user. The parameter {1} can be used if you - want to filter on the login name. - - So if we used the following configuration - ]]> and authenticated successfully as user ben, the subsequent - loading of authorities would perform a search under the directory entry - ou=groups,dc=springframework,dc=org, looking for entries which - contain the attribute uniqueMember with value - uid=ben,ou=people,dc=springframework,dc=org. By default the - authority names will have the prefix ROLE_ prepended. You can - change this using the role-prefix attribute. If you don't want - any prefix, use role-prefix="none". For more information on - loading authorities, see the Javadoc for the - DefaultLdapAuthoritiesPopulator class. -
-
-
- - Implementation Classes - - The namespace configuration options we've used above are simple to use and much more - concise than using Spring beans explicitly. There are situations when you may need to - know how to configure Spring Security LDAP directly in your application context. You may - wish to customize the behaviour of some of the classes, for example. If you're happy - using namespace configuration then you can skip this section and the next one. - The main LDAP provider class, LdapAuthenticationProvider, - doesn't actually do much itself but delegates the work to two other beans, an - LdapAuthenticator and an - LdapAuthoritiesPopulator which are responsible for - authenticating the user and retrieving the user's set of - GrantedAuthoritys respectively. -
- - LdapAuthenticator Implementations - - The authenticator is also responsible for retrieving any required user attributes. - This is because the permissions on the attributes may depend on the type of - authentication being used. For example, if binding as the user, it may be necessary - to read them with the user's own permissions. - There are currently two authentication strategies supplied with Spring Security: - - Authentication directly to the LDAP server ("bind" authentication). - - - Password comparison, where the password supplied by the user is compared - with the one stored in the repository. This can either be done by retrieving - the value of the password attribute and checking it locally or by performing - an LDAP "compare" operation, where the supplied password is passed to the - server for comparison and the real password value is never retrieved. - - -
- - Common Functionality - - Before it is possible to authenticate a user (by either strategy), the - distinguished name (DN) has to be obtained from the login name supplied to the - application. This can be done either by simple pattern-matching (by setting the - setUserDnPatterns array property) or by setting the - userSearch property. For the DN pattern-matching approach, - a standard Java pattern format is used, and the login name will be substituted - for the parameter {0}. The pattern should be relative to - the DN that the configured - SpringSecurityContextSource will bind to (see the - section on connecting to the LDAP - server for more information on this). For example, if you are using an - LDAP server with the URL - ldap://monkeymachine.co.uk/dc=springframework,dc=org, and - have a pattern uid={0},ou=greatapes, then a login name of - "gorilla" will map to a DN - uid=gorilla,ou=greatapes,dc=springframework,dc=org. Each - configured DN pattern will be tried in turn until a match is found. For - information on using a search, see the section on search objects below. A combination of the - two approaches can also be used - the patterns will be checked first and if no - matching DN is found, the search will be used. -
-
- - BindAuthenticator - - The class BindAuthenticator in the package - org.springframework.security.ldap.authentication implements - the bind authentication strategy. It simply attempts to bind as the user. -
-
- - PasswordComparisonAuthenticator - - The class PasswordComparisonAuthenticator implements - the password comparison authentication strategy. -
-
-
- - Connecting to the LDAP Server - - The beans discussed above have to be able to connect to the server. They both have - to be supplied with a SpringSecurityContextSource - which is an extension of Spring LDAP's ContextSource. - Unless you have special requirements, you will usually configure a - DefaultSpringSecurityContextSource bean, which can be - configured with the URL of your LDAP server and optionally with the username and - password of a "manager" user which will be used by default when binding to the - server (instead of binding anonymously). For more information read the Javadoc for - this class and for Spring LDAP's AbstractContextSource. - -
-
- - LDAP Search Objects - - Often a more complicated strategy than simple DN-matching is required to locate a - user entry in the directory. This can be encapsulated in an - LdapUserSearch instance which can be supplied to the - authenticator implementations, for example, to allow them to locate a user. The - supplied implementation is FilterBasedLdapUserSearch. -
- - - <classname>FilterBasedLdapUserSearch</classname> - - This bean uses an LDAP filter to match the user object in the directory. The - process is explained in the Javadoc for the corresponding search method on the - JDK DirContext class. As explained there, the search filter can be - supplied with parameters. For this class, the only valid parameter is - {0} which will be replaced with the user's login - name. -
-
-
- LdapAuthoritiesPopulator - After authenticating the user successfully, the - LdapAuthenticationProvider will attempt to load a set of - authorities for the user by calling the configured - LdapAuthoritiesPopulator bean. The - DefaultLdapAuthoritiesPopulator is an implementation which - will load the authorities by searching the directory for groups of which the user is - a member (typically these will be groupOfNames or - groupOfUniqueNames entries in the directory). Consult the Javadoc - for this class for more details on how it works. - If you want to use LDAP only for authentication, but load the authorities from a - difference source (such as a database) then you can provide your own implementation - of this interface and inject that instead. -
-
- - Spring Bean Configuration - - A typical configuration, using some of the beans we've discussed here, might look - like this: - - - - - - - - - - - uid={0},ou=people - - - - - - - - - - -]]> - This would set up the provider to access an LDAP server - with URL ldap://monkeymachine:389/dc=springframework,dc=org. - Authentication will be performed by attempting to bind with the DN - uid=<user-login-name>,ou=people,dc=springframework,dc=org. - After successful authentication, roles will be assigned to the user by searching - under the DN ou=groups,dc=springframework,dc=org with the default - filter (member=<user's-DN>). The role name will be taken - from the ou attribute of each match. - To configure a user search object, which uses the filter - (uid=<user-login-name>) for use instead of the DN-pattern - (or in addition to it), you would configure the following bean - - - - ]]> - and use it by setting the - BindAuthenticator bean's userSearch - property. The authenticator would then call the search object to obtain the correct - user's DN before attempting to bind as this user. -
-
- LDAP Attributes and Customized UserDetails - The net result of an authentication using - LdapAuthenticationProvider is the same as a normal Spring - Security authentication using the standard - UserDetailsService interface. A - UserDetails object is created and stored in the - returned Authentication object. As with using a - UserDetailsService, a common requirement is to be - able to customize this implementation and add extra properties. When using LDAP, - these will normally be attributes from the user entry. The creation of the - UserDetails object is controlled by the provider's - UserDetailsContextMapper strategy, which is - responsible for mapping user objects to and from LDAP context data: authorities); - - void mapUserToContext(UserDetails user, DirContextAdapter ctx); -}]]> - Only the first method is relevant for authentication. If you - provide an implementation of this interface and inject it into the - LdapAuthenticationProvider, you have control over exactly how - the UserDetails object is created. The first parameter is an instance of Spring - LDAP's DirContextOperations which gives you access to - the LDAP attributes which were loaded during authentication. The - username parameter is the name used to authenticate and the final - parameter is the collection of authorities loaded for the user by the configured - LdapAuthoritiesPopulator. - The way the context data is loaded varies slightly depending on the type of - authentication you are using. With the BindAuthenticator, the - context returned from the bind operation will be used to read the attributes, - otherwise the data will be read using the standard context obtained from the - configured ContextSource (when a search is configured - to locate the user, this will be the data returned by the search object). -
-
-
- Active Directory Authentication - Active Directory supports its own non-standard authentication options, and the normal usage pattern - doesn't fit too cleanly with the standard LdapAuthenticationProvider. - Typically authentication is performed using the domain username (in the form user@domain), - rather than using an LDAP distinguished name. To make this easier, Spring Security 3.1 has an - authentication provider which is customized for a typical Active Directory setup. - -
- <classname>ActiveDirectoryLdapAuthenticationProvider</classname> - Configuring ActiveDirectoryLdapAuthenticationProvider is - quite straightforward. You just need to supply the domain name and an LDAP URL - supplying the address of the server - It is also possible to obtain the server's IP address using a DNS lookup. This - is not currently supported, but hopefully will be in a future version. - . An example configuration would then look like this: - - - -}]]> - Note that there is no need to specify a separate - ContextSource in order to define the server location - the bean - is completely self-contained. A user named Sharon, for example, would - then be able to authenticate by entering either the username - sharon or the full Active Directory - userPrincipalName, namely sharon@mydomain.com. - The user's directory entry will then be located, and the attributes returned for - possible use in customizing the created UserDetails - object (a UserDetailsContextMapper can be injected - for this purpose, as described above). All interaction with the directory takes - place with the identity of the user themselves. There is no concept of a - manager user. - By default, the user authorities are obtained from the memberOf - attribute values of the user entry. The authorities allocated to the user can again - be customized using a UserDetailsContextMapper. You - can also inject a GrantedAuthoritiesMapper into the - provider instance to control the authorities which end up in the - Authentication object. -
- Active Directory Error Codes - By default, a failed result will cause a standard Spring Security - BadCredentialsException. If you set the property - convertSubErrorCodesToExceptions to true, - the exception messages will be parsed to attempt to extract the Active - Directory-specific error code and raise a more specific exception. Check the - class Javadoc for more information. -
-
-
-
diff --git a/docs/manual/src/docbook/namespace-config.xml b/docs/manual/src/docbook/namespace-config.xml deleted file mode 100644 index a5cea5c642..0000000000 --- a/docs/manual/src/docbook/namespace-config.xml +++ /dev/null @@ -1,1029 +0,0 @@ - - - - Security Namespace Configuration - -
- Introduction - Namespace configuration has been available since version 2.0 of the Spring framework. - It allows you to supplement the traditional Spring beans application context syntax with - elements from additional XML schema. You can find more information in the Spring Reference Documentation. A namespace element can be used simply to allow a more - concise way of configuring an individual bean or, more powerfully, to define an - alternative configuration syntax which more closely matches the problem domain and hides - the underlying complexity from the user. A simple element may conceal the fact that - multiple beans and processing steps are being added to the application context. For - example, adding the following element from the security namespace to an application - context will start up an embedded LDAP server for testing use within the application: -]]> This is much simpler than wiring up the equivalent Apache Directory Server - beans. The most common alternative configuration requirements are supported by - attributes on the ldap-server element and the user is isolated from - worrying about which beans they need to create and what the bean property names are. - You can find out more about the use of the ldap-server element - in the chapter on LDAP. - . Use of a good XML editor while editing the application context file should - provide information on the attributes and elements that are available. We would - recommend that you try out the SpringSource Tool Suite as - it has special features for working with standard Spring namespaces. - To start using the security namespace in your application context, you need to have - the spring-security-config jar on your classpath. Then all you need - to do is add the schema declaration to your application context file: - - ... - - ]]> In many of the examples you will see (and in the sample) applications, we - will often use "security" as the default namespace rather than "beans", which means we - can omit the prefix on all the security namespace elements, making the content easier to - read. You may also want to do this if you have your application context divided up into - separate files and have most of your security configuration in one of them. Your - security application context file would then start like this - ... - -]]> We'll assume this syntax is being used from now on in this chapter. -
- Design of the Namespace - The namespace is designed to capture the most common uses of the framework and - provide a simplified and concise syntax for enabling them within an application. The - design is based around the large-scale dependencies within the framework, and can be - divided up into the following areas: - - Web/HTTP Security - the most complex part. Sets up - the filters and related service beans used to apply the framework - authentication mechanisms, to secure URLs, render login and error pages and - much more. - - - Business Object (Method) Security - options for - securing the service layer. - - - AuthenticationManager - handles authentication - requests from other parts of the framework. - - - AccessDecisionManager - provides access decisions - for web and method security. A default one will be registered, but you can - also choose to use a custom one, declared using normal Spring bean - syntax. - - - AuthenticationProviders - mechanisms against which - the authentication manager authenticates users. The namespace provides - supports for several standard options and also a means of adding custom - beans declared using a traditional syntax. - - - UserDetailsService - closely related to - authentication providers, but often also required by other beans. - - - - We'll see how to configure these in the following sections. -
-
-
- Getting Started with Security Namespace Configuration - In this section, we'll look at how you can build up a namespace configuration to use - some of the main features of the framework. Let's assume you initially want to get up - and running as quickly as possible and add authentication support and access control to - an existing web application, with a few test logins. Then we'll look at how to change - over to authenticating against a database or other security repository. In later - sections we'll introduce more advanced namespace configuration options. -
- <literal>web.xml</literal> Configuration - The first thing you need to do is add the following filter declaration to your - web.xml file: - springSecurityFilterChain - org.springframework.web.filter.DelegatingFilterProxy - - - - springSecurityFilterChain - /* -]]> - This provides a hook into the Spring Security web - infrastructure. DelegatingFilterProxy is a Spring Framework - class which delegates to a filter implementation which is defined as a Spring bean - in your application context. In this case, the bean is named - springSecurityFilterChain, which is an internal infrastructure bean - created by the namespace to handle web security. Note that you should not use this - bean name yourself. Once you've added this to your web.xml, - you're ready to start editing your application context file. Web security services - are configured using the <http> element. -
-
- A Minimal <literal><http></literal> Configuration - All you need to enable web security to begin with is - - - - - ]]> - Which says that we want all URLs within our application to be secured, - requiring the role ROLE_USER to access them, we want to log in to - the application using a form with username and password, and that we want a logout URL - registered which will allow us to log out of the application. - <http> element is the parent for all web-related namespace - functionality. The <intercept-url> element defines a - pattern which is matched against the URLs of incoming requests - using an ant path style syntax - See the section on Request - Matching in the Web Application Infrastructure chapter for more details - on how matches are actually performed. - . You can also use regular-expression matching as an alternative (see the - namespace appendix for more details). The access attribute - defines the access requirements for requests matching the given pattern. With the - default configuration, this is typically a comma-separated list of roles, one of - which a user must have to be allowed to make the request. The prefix - ROLE_ is a marker which indicates that a simple comparison with the - user's authorities should be made. In other words, a normal role-based check should - be used. Access-control in Spring Security is not limited to the use of simple roles - (hence the use of the prefix to differentiate between different types of security - attributes). We'll see later how the interpretation can vary - The interpretation of the comma-separated values in the - access attribute depends on the implementation of the AccessDecisionManager which is used. In - Spring Security 3.0, the attribute can also be populated with an EL expression. - . - - You can use multiple <intercept-url> elements to - define different access requirements for different sets of URLs, but they will - be evaluated in the order listed and the first match will be used. So you must - put the most specific matches at the top. You can also add a - method attribute to limit the match to a particular HTTP - method (GET, POST, PUT - etc.). - - To add some users, you can define a set of test data directly in the namespace: - - - - - - - - ]]> - - - If you are familiar with pre-namespace versions of the framework, you can - probably already guess roughly what's going on here. The - <http> element is responsible for creating a - FilterChainProxy and the filter beans which it uses. - Common problems like incorrect filter ordering are no longer an issue as the - filter positions are predefined. - The <authentication-provider> element creates a - DaoAuthenticationProvider bean and the - <user-service> element creates an - InMemoryDaoImpl. All - authentication-provider elements must be children of the - <authentication-manager> element, which creates a - ProviderManager and registers the authentication - providers with it. You can find more detailed information on the beans that are - created in the namespace appendix. - It's worth cross-checking this if you want to start understanding what the - important classes in the framework are and how they are used, particularly if - you want to customise things later. - - The configuration above defines two users, their passwords and their roles within - the application (which will be used for access control). It is also possible to load - user information from a standard properties file using the - properties attribute on user-service. See the - section on in-memory - authentication for more details on the file format. Using the - <authentication-provider> element means that the user - information will be used by the authentication manager to process authentication - requests. You can have multiple <authentication-provider> - elements to define different authentication sources and each will be consulted in - turn. - At this point you should be able to start up your application and you will be - required to log in to proceed. Try it out, or try experimenting with the - tutorial sample application that comes with the project. -
-
- Form and Basic Login Options - You might be wondering where the login form came from when you were prompted to - log in, since we made no mention of any HTML files or JSPs. In fact, since we didn't - explicitly set a URL for the login page, Spring Security generates one - automatically, based on the features that are enabled and using standard values for - the URL which processes the submitted login, the default target URL the user will be - sent to after logging in and so on. However, the namespace offers plenty of support - to allow you to customize these options. For example, if you want to supply your own - login page, you could use: - - - - - ]]> - Also note - that we've added an extra intercept-url element to say that any - requests for the login page should be available to anonymous users - See the chapter on anonymous - authentication and also the AuthenticatedVoter class for more details on how the value - IS_AUTHENTICATED_ANONYMOUSLY is processed. - . Otherwise the request would be matched by the pattern - /** and it wouldn't be possible to access the login page itself! - This is a common configuration error and will result in an infinite loop in the - application. Spring Security will emit a warning in the log if your login page - appears to be secured. It is also possible to have all requests matching a - particular pattern bypass the security filter chain completely, by defining a - separate http element for the pattern like this: - - - - - - - ]]> - From Spring Security 3.1 it is now possible to use multiple - http elements to define separate security filter chain - configurations for different request patterns. If the pattern - attribute is omitted from an http element, it matches all - requests. Creating an unsecured pattern is a simple example of this syntax, where - the pattern is mapped to an empty filter chain - The use of multiple <http> elements is an important - feature, allowing the namespace to simultaneously support both stateful and - stateless paths within the same application, for example. The previous syntax, - using the attribute filters="none" on an - intercept-url element is incompatible with this change and is - no longer supported in 3.1. - . We'll look at this new syntax in more detail in the chapter on the - Security Filter Chain. - It's important to realise that these unsecured requests will be completely - oblivious to any Spring Security web-related configuration or additional attributes - such as requires-channel, so you will not be able to access - information on the current user or call secured methods during the request. Use - access='IS_AUTHENTICATED_ANONYMOUSLY' as an alternative if you - still want the security filter chain to be applied. - If you want to use basic authentication instead of form login, then change the - configuration to - - - - ]]> - Basic authentication will then take precedence and will be used to - prompt for a login when a user attempts to access a protected resource. Form login - is still available in this configuration if you wish to use it, for example through - a login form embedded in another web page. -
- Setting a Default Post-Login Destination - If a form login isn't prompted by an attempt to access a protected resource, - the default-target-url option comes into play. This is the - URL the user will be taken to after successfully logging in, and defaults to - "/". You can also configure things so that the user always - ends up at this page (regardless of whether the login was "on-demand" or they - explicitly chose to log in) by setting the - always-use-default-target attribute to "true". This is useful - if your application always requires that the user starts at a "home" page, for - example: - - - - - ]]> - For even more control over the destination, you can use the - authentication-success-handler-ref attribute as an - alternative to default-target-url. The referenced bean should - be an instance of AuthenticationSuccessHandler. - You'll find more on this in the Core Filters chapter and also in the namespace appendix, as well as - information on how to customize the flow when authentication fails. -
-
-
- Logout Handling - The logout element adds support for logging out by navigating - to a particular URL. The default logout URL is /j_spring_security_logout, - but you can set it to something else using the logout-url attribute. - More information on other available attributes may be found in the namespace appendix. - -
-
- Using other Authentication Providers - In practice you will need a more scalable source of user information than a few - names added to the application context file. Most likely you will want to store your - user information in something like a database or an LDAP server. LDAP namespace - configuration is dealt with in the LDAP chapter, so - we won't cover it here. If you have a custom implementation of Spring Security's - UserDetailsService, called "myUserDetailsService" in your - application context, then you can authenticate against this using - - - ]]> - If you want to use a database, then you can use - - - - - ]]> - Where securityDataSource is the name of a - DataSource bean in the application context, pointing at a - database containing the standard Spring Security user data tables. Alternatively, - you could configure a Spring Security JdbcDaoImpl bean and - point at that using the user-service-ref attribute: - - - - - - - ]]> - You can also use standard - AuthenticationProvider beans as follows - - - ]]> - where myAuthenticationProvider is the name of a - bean in your application context which implements - AuthenticationProvider. You can use multiple - authentication-provider elements, in which case the providers - will be queried in the order they are declared. See for more on information on how the Spring Security - AuthenticationManager is configured using the - namespace. -
- Adding a Password Encoder - Passwords should always be encoded using a secure hashing algorithm designed for the purpose - (not a standard algorithm like SHA or MD5). This is supported by the - <password-encoder> element. With bcrypt - encoded passwords, the original authentication provider configuration would look - like this: - - - - - - - - - - - ]]> - - Bcrypt is a good choice for most cases, unless you have a legacy system which forces - you to use a different algorithm. If you are using a simple hashing algorithm or, even worse, - storing plain text passwords, then you should consider migrating to a more secure option like bcrypt. - -
-
-
-
- Advanced Web Features -
- Remember-Me Authentication - See the separate Remember-Me chapter for - information on remember-me namespace configuration. -
-
- Adding HTTP/HTTPS Channel Security - If your application supports both HTTP and HTTPS, and you require that particular - URLs can only be accessed over HTTPS, then this is directly supported using the - requires-channel attribute on - <intercept-url>: - - - ... - ]]> - With this configuration in place, if a user attempts to access - anything matching the "/secure/**" pattern using HTTP, they will first be redirected - to an HTTPS URL - For more details on how channel-processing is implemented, see the Javadoc - for ChannelProcessingFilter and related classes. - . - The available options are "http", "https" or "any". Using the value - "any" means that either HTTP or HTTPS can be used. - If your application uses non-standard ports for HTTP and/or HTTPS, you can specify - a list of port mappings as follows: - ... - - - - ]]> - - Note that in order to be truly secure, an application should not use HTTP at all or switch - between HTTP and HTTPS. It should start in HTTPS (with the user entering an HTTPS URL) and - use a secure connection throughout to avoid any possibility of man-in-the-middle attacks. - -
-
- Session Management -
- Detecting Timeouts - You can configure Spring Security to detect the submission of an invalid - session ID and redirect the user to an appropriate URL. This is achieved through - the session-management element: - ... - - ]]>Note that if you use this mechanism to detect session timeouts, it - may falsely report an error if the user logs out and then logs back in without - closing the browser. This is because the session cookie is not cleared when you - invalidate the session and will be resubmitted even if the user has logged out. - You may be able to explicitly delete the JSESSIONID cookie on logging out, for - example by using the following syntax in the logout handler: - - - ]]> Unfortunately this can't be guaranteed to work with every servlet container, - so you will need to test it in your environment - If you are running your application behind a proxy, you may also be able - to remove the session cookie by configuring the proxy server. For example, - using Apache HTTPD's mod_headers, the following directive would delete the - JSESSIONID cookie by expiring it in the response to a - logout request (assuming the application is deployed under the path - /tutorial): - <LocationMatch "/tutorial/j_spring_security_logout"> - Header always set Set-Cookie "JSESSIONID=;Path=/tutorial;Expires=Thu, 01 Jan 1970 00:00:00 GMT" - </LocationMatch> - . -
-
- Concurrent Session Control - If you wish to place constraints on a single user's ability to log in to your - application, Spring Security supports this out of the box with the following - simple additions. First you need to add the following listener to your - web.xml file to keep Spring Security updated about session - lifecycle events: - - org.springframework.security.web.session.HttpSessionEventPublisher - - -]]> Then add the following lines to your application context: - ... - - - - ]]> - This will prevent a user from logging in multiple times - a - second login will cause the first to be invalidated. Often you would prefer to - prevent a second login, in which case you can use - ... - - - - ]]> - The second login will then be rejected. By - rejected, we mean that the user will be sent to the - authentication-failure-url if form-based login is being used. - If the second authentication takes place through another non-interactive - mechanism, such as remember-me, an unauthorized - (401) error will be sent to the client. If instead you want to use an error - page, you can add the attribute - session-authentication-error-url to the - session-management element. - If you are using a customized authentication filter for form-based login, then - you have to configure concurrent session control support explicitly. More - details can be found in the Session Management - chapter. -
-
- Session Fixation Attack Protection - Session - fixation attacks are a potential risk where it is possible for a - malicious attacker to create a session by accessing a site, then persuade - another user to log in with the same session (by sending them a link containing - the session identifier as a parameter, for example). Spring Security protects - against this automatically by creating a new session or otherwise changing the - session ID when a user logs in. If you don't require this protection, or it - conflicts with some other requirement, you can control the behavior using the - session-fixation-protection attribute on - <session-management>, which has four options - - none - Don't do anything. The original session will - be retained. - - - newSession - Create a new "clean" session, without - copying the existing session data (Spring Security-related attributes will - still be copied). - - - migrateSession - Create a new session and copy - all existing session attributes to the new session. This is the - default in Servlet 3.0 or older containers. - - - changeSessionId - Do not create a new session. - Instead, use the session fixation protection provided by the Servlet container - (HttpServletRequest#changeSessionId()). This option is only - available in Servlet 3.1 (Java EE 7) and newer containers. Specifying it in - older containers will result in an exception. This is the default in Servlet - 3.1 and newer containers. - - - When session fixation protection occurs, it results in a - SessionFixationProtectionEvent being published in the - application context. If you use changeSessionId, this protection - will also result in any - javax.servlet.http.HttpSessionIdListeners being notified, so - use caution if your code listens for both events. See the - Session Management chapter for additional - information. - -
-
-
- OpenID Support - The namespace supports OpenID login - either instead of, or in addition to normal form-based login, with a simple change: - - - -]]>You should then register yourself with an OpenID provider (such as - myopenid.com), and add the user information to your in-memory - <user-service> : -]]> You should be able to login using the myopenid.com site to - authenticate. It is also possible to select a specific - UserDetailsService bean for use OpenID by setting the - user-service-ref attribute on the openid-login - element. See the previous section on authentication providers for more information. Note that we have omitted the - password attribute from the above user configuration, since this set of user data is - only being used to load the authorities for the user. A random password will be - generate internally, preventing you from accidentally using this user data as an - authentication source elsewhere in your configuration. -
- Attribute Exchange - Support for OpenID attribute exchange. As an example, the following configuration would - attempt to retrieve the email and full name from the OpenID provider, for use by - the application: - - - - - ]]>The type of each OpenID attribute is a URI, - determined by a particular schema, in this case http://axschema.org/. If an attribute - must be retrieved for successful authentication, the required - attribute can be set. The exact schema and attributes supported will depend on - your OpenID provider. The attribute values are returned as part of the - authentication process and can be accessed afterwards using the following code: - -OpenIDAuthenticationToken token = - (OpenIDAuthenticationToken)SecurityContextHolder.getContext().getAuthentication(); -List<OpenIDAttribute> attributes = token.getAttributes();The - OpenIDAttribute contains the attribute type and the - retrieved value (or values in the case of multi-valued attributes). We'll see - more about how the SecurityContextHolder class is used - when we look at core Spring Security components in the technical overview chapter. Multiple - attribute exchange configurations are also be supported, if you wish to use - multiple identity providers. You can supply multiple - attribute-exchange elements, using an - identifier-matcher attribute on each. This contains a regular - expression which will be matched against the OpenID identifier supplied by the - user. See the OpenID sample application in the codebase for an example - configuration, providing different attribute lists for the Google, Yahoo and - MyOpenID providers. -
-
-
- Response Headers - A lot of different attacks to hijack content, sessions or connections are available and lately - browsers (optionally) can help to prevent those attacks. To enable these features we need to send some - additional headers to the client. Spring Security allows for easy configuration for several headers. - - ... - -]]> - - - Specifying the single headers element adds all the explicitly supported headers - with their default settings. If you only want select headers to be added, - you can add one or more of the child elements as shown below. - - ... - - - - - - -
- <-- Adds HTTP Strict Transport Security (HSTS) for secure requests --> - - - - - - -]]> - - - For additional information on how to customize the headers element refer to the Security Headers - section of the reference. -
-
- Adding in Your Own Filters - If you've used Spring Security before, you'll know that the framework maintains a - chain of filters in order to apply its services. You may want to add your own - filters to the stack at particular locations or use a Spring Security filter for - which there isn't currently a namespace configuration option (CAS, for example). Or - you might want to use a customized version of a standard namespace filter, such as - the UsernamePasswordAuthenticationFilter which is created by the - <form-login> element, taking advantage of some of the extra - configuration options which are available by using the bean explicitly. How can you - do this with namespace configuration, since the filter chain is not directly - exposed? - The order of the filters is always strictly enforced when using the namespace. - When the application context is being created, the filter beans are sorted by the - namespace handling code and the standard Spring Security filters each have an alias - in the namespace and a well-known position. - In previous versions, the sorting took place after the filter instances had - been created, during post-processing of the application context. In version 3.0+ - the sorting is now done at the bean metadata level, before the classes have been - instantiated. This has implications for how you add your own filters to the - stack as the entire filter list must be known during the parsing of the - <http> element, so the syntax has changed slightly in - 3.0. - The filters, aliases and namespace elements/attributes which create the - filters are shown in . The filters are listed in the - order in which they occur in the filter chain. - Standard Filter Aliases and Ordering - - - - - - - Alias - Filter Class - Namespace Element or Attribute - - - - - CHANNEL_FILTER - ChannelProcessingFilter - http/intercept-url@requires-channel - - - SECURITY_CONTEXT_FILTER - SecurityContextPersistenceFilter - http - - - CONCURRENT_SESSION_FILTER - ConcurrentSessionFilter - session-management/concurrency-control - - - HEADERS_FILTER - HeaderWriterFilter - http/headers - - - CSRF_FILTER - CsrfFilter - http/csrf - - - LOGOUT_FILTER - LogoutFilter - http/logout - - - X509_FILTER - X509AuthenticationFilter - http/x509 - - - PRE_AUTH_FILTER - AstractPreAuthenticatedProcessingFilter - Subclasses - N/A - - - CAS_FILTER - CasAuthenticationFilter - N/A - - - FORM_LOGIN_FILTER - UsernamePasswordAuthenticationFilter - http/form-login - - - BASIC_AUTH_FILTER - BasicAuthenticationFilter - http/http-basic - - - SERVLET_API_SUPPORT_FILTER - SecurityContextHolderAwareRequestFilter - http/@servlet-api-provision - - - JAAS_API_SUPPORT_FILTER - JaasApiIntegrationFilter - http/@jaas-api-provision - - - REMEMBER_ME_FILTER - RememberMeAuthenticationFilter - http/remember-me - - - ANONYMOUS_FILTER - AnonymousAuthenticationFilter - http/anonymous - - - SESSION_MANAGEMENT_FILTER - SessionManagementFilter - session-management - - - EXCEPTION_TRANSLATION_FILTER - ExceptionTranslationFilter - http - - - FILTER_SECURITY_INTERCEPTOR - FilterSecurityInterceptor - http - - - SWITCH_USER_FILTER - SwitchUserFilter - N/A - - - -
You can add your own filter to the stack, using the - custom-filter element and one of these names to specify the - position your filter should appear at: - - - - - ]]> - You can also use the after or before - attributes if you want your filter to be inserted before or after another filter in - the stack. The names "FIRST" and "LAST" can be used with the - position attribute to indicate that you want your filter to - appear before or after the entire stack, respectively.
- - Avoiding filter position conflicts - If you are inserting a custom filter which may occupy the same position as - one of the standard filters created by the namespace then it's important that - you don't include the namespace versions by mistake. Remove any elements which create - filters whose functionality you want to replace. - Note that you can't replace filters which are created by the use of the - <http> element itself - - SecurityContextPersistenceFilter, - ExceptionTranslationFilter or - FilterSecurityInterceptor. Some other filters are added - by default, but you can disable them. An AnonymousAuthenticationFilter - is added by default and unless you have - session-fixation protection - disabled, a SessionManagementFilter will also be added - to the filter chain. - - - If you're replacing a namespace filter which requires an authentication entry - point (i.e. where the authentication process is triggered by an attempt by an - unauthenticated user to access to a secured resource), you will need to add a custom - entry point bean too. -
- Setting a Custom - <interfacename>AuthenticationEntryPoint</interfacename> - If you aren't using form login, OpenID or basic authentication through the - namespace, you may want to define an authentication filter and entry point using - a traditional bean syntax and link them into the namespace, as we've just seen. - The corresponding AuthenticationEntryPoint can be - set using the entry-point-ref attribute on the - <http> element. - The CAS sample application is a good example of the use of custom beans with - the namespace, including this syntax. If you aren't familiar with authentication - entry points, they are discussed in the technical overview chapter. - -
-
-
-
- Method Security - From version 2.0 onwards Spring Security has improved support substantially for adding - security to your service layer methods. It provides support for JSR-250 annotation - security as well as the framework's original @Secured annotation. - From 3.0 you can also make use of new expression-based - annotations. You can apply security to a single bean, using the - intercept-methods element to decorate the bean declaration, or you - can secure multiple beans across the entire service layer using the AspectJ style - pointcuts. -
- The <literal><global-method-security></literal> Element - This element is used to enable annotation-based security in your application (by - setting the appropriate attributes on the element), and also to group together - security pointcut declarations which will be applied across your entire application - context. You should only declare one - <global-method-security> element. The following declaration - would enable support for Spring Security's @Secured: - ]]> - Adding an annotation to a method (on an class or interface) would then limit - the access to that method accordingly. Spring Security's native annotation support - defines a set of attributes for the method. These will be passed to the - AccessDecisionManager for it to make the actual - decision: - - public interface BankService { - - @Secured("IS_AUTHENTICATED_ANONYMOUSLY") - public Account readAccount(Long id); - - @Secured("IS_AUTHENTICATED_ANONYMOUSLY") - public Account[] findAccounts(); - - @Secured("ROLE_TELLER") - public Account post(Account account, double amount); - } -Support - for JSR-250 annotations can be enabled using - ]]> - These are standards-based and allow simple role-based constraints to - be applied but do not have the power Spring Security's native annotations. To use - the new expression-based syntax, you would use - ]]>and the equivalent Java code would - be - public interface BankService { - - @PreAuthorize("isAnonymous()") - public Account readAccount(Long id); - - @PreAuthorize("isAnonymous()") - public Account[] findAccounts(); - - @PreAuthorize("hasAuthority('ROLE_TELLER')") - public Account post(Account account, double amount); - } - Expression-based - annotations are a good choice if you need to define simple rules that go beyond - checking the role names against the user's list of authorities. - The annotated methods will only be secured for instances which are defined as - Spring beans (in the same application context in which method-security is - enabled). If you want to secure instances which are not created by Spring (using - the new operator, for example) then you need to use AspectJ. - - - - - You can enable more than one type of annotation in the same application, but - only one type should be used for any interface or class as the behaviour will not - be well-defined otherwise. If two annotations are found which apply to a particular - method, then only one of them will be applied. - - -
- Adding Security Pointcuts using <literal>protect-pointcut</literal> - The use of protect-pointcut is particularly powerful, as - it allows you to apply security to many beans with only a simple declaration. - Consider the following example: - - -]]> - This will protect all methods on beans declared in the application - context whose classes are in the com.mycompany package and - whose class names end in "Service". Only users with the - ROLE_USER role will be able to invoke these methods. As with - URL matching, the most specific matches must come first in the list of - pointcuts, as the first matching expression will be used. Security - annotations take precedence over pointcuts. - -
-
-
-
- The Default AccessDecisionManager - This section assumes you have some knowledge of the underlying architecture for - access-control within Spring Security. If you don't you can skip it and come back to it - later, as this section is only really relevant for people who need to do some - customization in order to use more than simple role-based security. - When you use a namespace configuration, a default instance of - AccessDecisionManager is automatically registered for you - and will be used for making access decisions for method invocations and web URL access, - based on the access attributes you specify in your intercept-url and - protect-pointcut declarations (and in annotations if you are using - annotation secured methods). - The default strategy is to use an AffirmativeBased - AccessDecisionManager with a - RoleVoter and an AuthenticatedVoter. You - can find out more about these in the chapter on authorization. -
- Customizing the AccessDecisionManager - If you need to use a more complicated access control strategy then it is easy to - set an alternative for both method and web security. - For method security, you do this by setting the - access-decision-manager-ref attribute on - global-method-security to the id of the appropriate - AccessDecisionManager bean in the application - context: - ... - - ]]> - The syntax for web security is the same, but on the http - element: - ... - - ]]> -
-
-
- The Authentication Manager and the Namespace - The main interface which provides authentication services in Spring Security is the - AuthenticationManager. This is usually an instance of - Spring Security's ProviderManager class, which you may already be - familiar with if you've used the framework before. If not, it will be covered later, in - the technical overview chapter. The - bean instance is registered using the authentication-manager - namespace element. You can't use a custom AuthenticationManager - if you are using either HTTP or method security through the namespace, but this should - not be a problem as you have full control over the - AuthenticationProviders that are used. - You may want to register additional AuthenticationProvider - beans with the ProviderManager and you can do this using the - <authentication-provider> element with the - ref attribute, where the value of the attribute is the name of the - provider bean you want to add. For example: - - - - - ... - - ]]> - Another common requirement is that another bean in the context may require a - reference to the AuthenticationManager. You can easily - register an alias for the AuthenticationManager and use - this name elsewhere in your application context. - ... - - - - - ... - - ]]> -
-
diff --git a/docs/manual/src/docbook/new-3-1.xml b/docs/manual/src/docbook/new-3-1.xml deleted file mode 100644 index 68102e0315..0000000000 --- a/docs/manual/src/docbook/new-3-1.xml +++ /dev/null @@ -1,67 +0,0 @@ - - - What's new in Spring Security 3.1 - - This section contains summary of the updates found in Spring Security 3.1. A detailed list of changes can be found in the project's - JIRA -
- High level updates found Spring Security 3.1 - Below you can find a high level summary of updates to Spring Security 3.1. - - Support for multiple http elements - Support for stateless authentication - DebugFilter provides additional debugging information - Improved Active Directory LDAP support (i.e. ActiveDirectoryLdapAuthenticationProvider) - Added Basic Crypto Module. - The namespace is fully documented in the reference appendix. - Added dependencies section to the reference appendix - Support HttpOnly Flag for Cookies in Servlet 3.0 environments - InMemoryUserDetailsManager provides in memory implementation of UserDetailsManager - Support for hasPermission expression on the authorize JSP tag - Support for disabling UI security (for testing purposes) - Support erasing credentials after successful authentication - Support clearing cookies on logout - Spring Security Google App Engine example application - Support for CAS proxy tickets - Support for arbitrary implementations of JAAS Configuration - Support nested switching of users for SwitchUserFilter - -
-
- Spring Security 3.1 namespace updates - Below you can find a summary of updates to the Spring Security 3.1 namespace. - - Added support for multiple <http> elements and support for determining which one to use with - http@pattern, http@request-matcher, and - http@security. - Further information can be found in Namespace Configuration section of the reference. - Added stateless option for http@create-session - Added support for http@authentication-manager-ref - and global-method-security@authentication-manager-ref. - Added http@name - Added http@request-matcher-ref and - filter-chain@request-matcher-ref - Added <debug> - Added Support for setting the AuthenticationDetailsSource using the namespace. See - form-login@authentication-details-source-ref, - openid-login@authentication-details-source-ref, - http-basic@authentication-details-source-ref, and - x509@authentication-details-source-ref. - Added support for http/expression-handler. This allows - <expression-handler> to be used for web access expressions. - Added authentication-manager@erase-credentials - Added http-basic@entry-point-ref - Added logout@delete-cookies - Added remember-me@authentication-success-handler-ref - Added <metadata-source-ref> - Added global-method-security@metadata-source-ref - Added global-method-security@mode - Added <attribute-exchange> - Added remember-me@use-secure-cookie - Added http@jaas-api-provision - Added form-login@username-parameter and - form-login@password-parameter - -
-
diff --git a/docs/manual/src/docbook/packagecheck.sh b/docs/manual/src/docbook/packagecheck.sh deleted file mode 100755 index 93e8dbe22a..0000000000 --- a/docs/manual/src/docbook/packagecheck.sh +++ /dev/null @@ -1,3 +0,0 @@ -CLASSPATH=`find ../../../.. -name *.jar | grep -v sources | xargs | sed "s/ /:/g"` - -grep -o -e 'org.springframework.security\.[a-z]*\.[a-zA-Z0-9]*\.[A-Z][a-zA-z0-9]*' * | cut -d : -f 2 | xargs -n 1 javap -classpath "$CLASSPATH" | grep ERROR diff --git a/docs/manual/src/docbook/pdf-titlepage.xml b/docs/manual/src/docbook/pdf-titlepage.xml deleted file mode 100644 index 39371f2247..0000000000 --- a/docs/manual/src/docbook/pdf-titlepage.xml +++ /dev/null @@ -1,101 +0,0 @@ - - - - - - - - - - - - - - - - -]> - - - - - - <subtitle - text-align="center" - font-size="&hsize4;" - space-before="&hsize4space;" - font-family="{$title.fontset}" - /> - - <corpauthor space-before="0.5em" - font-size="&hsize2;" - /> - - <authorgroup space-before="0.5em" - font-size="&hsize2;" - /> - - <author space-before="0.5em" font-size="&hsize2;"/> - <mediaobject space-before="2em" space-after="2em"/> - <releaseinfo space-before="5em" font-size="&hsize2;"/> - - <othercredit space-before="2em" font-weight="normal" font-size="8"/> - <pubdate space-before="0.5em"/> - <revision space-before="0.5em"/> - <revhistory space-before="0.5em"/> - - <abstract space-before="0.5em" - text-align="start" - margin-left="0.1in" - margin-right="0.1in" - font-family="{$body.fontset}" - /> - </t:titlepage-content> - - <t:titlepage-content t:side="verso" text-align="start"> - <copyright space-before="1.5em"/> - <legalnotice space-before="15em"/> - </t:titlepage-content> - - <t:titlepage-separator> - </t:titlepage-separator> - - <t:titlepage-before t:side="recto"> - </t:titlepage-before> - - <t:titlepage-before t:side="verso"> - </t:titlepage-before> - </t:titlepage> - -<!-- ==================================================================== --> - -</t:templates> diff --git a/docs/manual/src/docbook/preauth.xml b/docs/manual/src/docbook/preauth.xml deleted file mode 100644 index db371b30e0..0000000000 --- a/docs/manual/src/docbook/preauth.xml +++ /dev/null @@ -1,192 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<chapter xmlns="http://docbook.org/ns/docbook" version="5.0" xml:id="preauth" - xmlns:xlink="http://www.w3.org/1999/xlink"> - <info> - <title>Pre-Authentication Scenarios - - There are situations where you want to use Spring Security for authorization, but the - user has already been reliably authenticated by some external system prior to accessing the - application. We refer to these situations as pre-authenticated scenarios. - Examples include X.509, Siteminder and authentication by the J2EE container in which the - application is running. When using pre-authentication, Spring Security has to - - Identify the user making the request. - - - Obtain the authorities for the user. - - The details will depend on the external authentication mechanism. A user might - be identified by their certificate information in the case of X.509, or by an HTTP request - header in the case of Siteminder. If relying on container authentication, the user will be - identified by calling the getUserPrincipal() method on the incoming - HTTP request. In some cases, the external mechanism may supply role/authority information - for the user but in others the authorities must be obtained from a separate source, such as - a UserDetailsService. -
- Pre-Authentication Framework Classes - Because most pre-authentication mechanisms follow the same pattern, Spring Security - has a set of classes which provide an internal framework for implementing - pre-authenticated authentication providers. This removes duplication and allows new - implementations to be added in a structured fashion, without having to write everything - from scratch. You don't need to know about these classes if you want to use something - like X.509 authentication, as it already has a namespace - configuration option which is simpler to use and get started with. If you need to use - explicit bean configuration or are planning on writing your own implementation then an - understanding of how the provided implementations work will be useful. You will find - classes under the - org.springframework.security.web.authentication.preauth. We just - provide an outline here so you should consult the Javadoc and source where appropriate. -
- AbstractPreAuthenticatedProcessingFilter - This class will check the current contents of the security context and, if empty, - it will attempt to extract user information from the HTTP request and submit it to - the AuthenticationManager. Subclasses override the - following methods to obtain this information: - - protected abstract Object getPreAuthenticatedPrincipal(HttpServletRequest request); - - protected abstract Object getPreAuthenticatedCredentials(HttpServletRequest request); - - After calling these, the filter will create a - PreAuthenticatedAuthenticationToken containing the returned - data and submit it for authentication. By authentication here, we - really just mean further processing to perhaps load the user's authorities, but the - standard Spring Security authentication architecture is followed. - Like other Spring Security authentication filters, the pre-authentication filter - has an authenticationDetailsSource property which by default will - create a WebAuthenticationDetails object to store additional - information such as the session-identifier and originating IP address in the - details property of the - Authentication object. In cases where user role - information can be obtained from the pre-authentication mechanism, the data is also - stored in this property, with the details implementing the - GrantedAuthoritiesContainer interface. This - enables the authentication provider to read the authorities which were externally - allocated to the user. We'll look at a concrete example next. -
- J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource - If the filter is configured with an - authenticationDetailsSource which is an instance of this - class, the authority information is obtained by calling the - isUserInRole(String role) method for each of a - pre-determined set of mappable roles. The class gets these from a - configured MappableAttributesRetriever. Possible - implementations include hard-coding a list in the application context and - reading the role information from the <security-role> - information in a web.xml file. The pre-authentication - sample application uses the latter approach. - There is an additional stage where the roles (or attributes) are mapped to - Spring Security GrantedAuthority objects using a - configured Attributes2GrantedAuthoritiesMapper. - The default will just add the usual ROLE_ prefix to the - names, but it gives you full control over the behaviour. -
-
-
- PreAuthenticatedAuthenticationProvider - The pre-authenticated provider has little more to do than load the - UserDetails object for the user. It does this by - delegating to a AuthenticationUserDetailsService. The - latter is similar to the standard UserDetailsService - but takes an Authentication object rather than just - user name: - - public interface AuthenticationUserDetailsService { - UserDetails loadUserDetails(Authentication token) throws UsernameNotFoundException; - } - - This interface may have also other uses but with pre-authentication it allows access - to the authorities which were packaged in the - Authentication object, as we saw in the previous - section. The - PreAuthenticatedGrantedAuthoritiesUserDetailsService class - does this. Alternatively, it may delegate to a standard - UserDetailsService via the - UserDetailsByNameServiceWrapper implementation. -
-
- Http403ForbiddenEntryPoint - The AuthenticationEntryPoint was discussed in the - technical overview chapter. - Normally it is responsible for kick-starting the authentication process for an - unauthenticated user (when they try to access a protected resource), but in the - pre-authenticated case this doesn't apply. You would only configure the - ExceptionTranslationFilter with an instance of this class if - you aren't using pre-authentication in combination with other authentication - mechanisms. It will be called if the user is rejected by the - AbstractPreAuthenticatedProcessingFilter resulting in a null - authentication. It always returns a 403-forbidden response code - if called. -
-
-
- Concrete Implementations - X.509 authentication is covered in its own chapter. - Here we'll look at some classes which provide support for other pre-authenticated - scenarios. -
- Request-Header Authentication (Siteminder) - An external authentication system may supply information to the application by - setting specific headers on the HTTP request. A well known example of this is - Siteminder, which passes the username in a header called SM_USER. - This mechanism is supported by the class - RequestHeaderAuthenticationFilter which simply extracts the - username from the header. It defaults to using the name SM_USER - as the header name. See the Javadoc for more details. - - Note that when using a system like this, the framework performs no - authentication checks at all and it is extremely important - that the external system is configured properly and protects all access to the - application. If an attacker is able to forge the headers in their original - request without this being detected then they could potentially choose any - username they wished. - -
- Siteminder Example Configuration - A typical configuration using this filter would look like this: - - - - - - - - - - - - - - - - - - - - -]]> - We've assumed here that the security namespace - is being used for configuration. It's also assumed that you have added a - UserDetailsService (called - userDetailsService) to your configuration to load the user's - roles. -
-
-
- J2EE Container Authentication - The class J2eePreAuthenticatedProcessingFilter will - extract the username from the userPrincipal property of the - HttpServletRequest. Use of this filter would usually - be combined with the use of J2EE roles as described above in . - There is a sample application in the codebase which uses this approach, so get - hold of the code from subversion and have a look at the application context file if - you are interested. The code is in the samples/preauth - directory. -
-
- diff --git a/docs/manual/src/docbook/remember-me-authentication.xml b/docs/manual/src/docbook/remember-me-authentication.xml deleted file mode 100644 index d5c4c6cd63..0000000000 --- a/docs/manual/src/docbook/remember-me-authentication.xml +++ /dev/null @@ -1,180 +0,0 @@ - - - Remember-Me Authentication - -
- - Overview - - Remember-me or persistent-login authentication refers to web sites being able to - remember the identity of a principal between sessions. This is typically accomplished by - sending a cookie to the browser, with the cookie being detected during future sessions - and causing automated login to take place. Spring Security provides the necessary hooks - for these operations to take place, and has two concrete remember-me implementations. - One uses hashing to preserve the security of cookie-based tokens and the other uses a - database or other persistent storage mechanism to store the generated tokens. - Note that both implemementations require a - UserDetailsService. If you are using an authentication - provider which doesn't use a UserDetailsService (for - example, the LDAP provider) then it won't work unless you also have a - UserDetailsService bean in your application context. - -
-
- Simple Hash-Based Token Approach - This approach uses hashing to achieve a useful remember-me strategy. In essence a - cookie is sent to the browser upon successful interactive authentication, with the - cookie being composed as follows: - - base64(username + ":" + expirationTime + ":" + - md5Hex(username + ":" + expirationTime + ":" password + ":" + key)) - - username: As identifiable to the UserDetailsService - password: That matches the one in the retrieved UserDetails - expirationTime: The date and time when the remember-me token expires, - expressed in milliseconds - key: A private key to prevent modification of the remember-me token - - As such the remember-me token is valid only for the period specified, and provided - that the username, password and key does not change. Notably, this has a potential - security issue in that a captured remember-me token will be usable from any user agent - until such time as the token expires. This is the same issue as with digest - authentication. If a principal is aware a token has been captured, they can easily - change their password and immediately invalidate all remember-me tokens on issue. If - more significant security is needed you should use the approach described in the next - section. Alternatively remember-me services should simply not be used at all. - If you are familiar with the topics discussed in the chapter on namespace configuration, you can enable remember-me - authentication just by adding the <remember-me> element: - ... - - - ]]> - The UserDetailsService will - normally be selected automatically. If you have more than one in your application - context, you need to specify which one should be used with the - user-service-ref attribute, where the value is the name of your - UserDetailsService bean. -
-
- Persistent Token Approach - This approach is based on the article http://jaspan.com/improved_persistent_login_cookie_best_practice with some minor - modifications - Essentially, the username is not included in the cookie, to prevent exposing a - valid login name unecessarily. There is a discussion on this in the comments section - of this article. - . To use the this approach with namespace configuration, you would supply a - datasource reference: - ... - - - ]]> - The database should contain a - persistent_logins table, created using the following SQL (or - equivalent): - - create table persistent_logins (username varchar(64) not null, - series varchar(64) primary key, - token varchar(64) not null, - last_used timestamp not null) - - -
-
- - Remember-Me Interfaces and Implementations - - Remember-me authentication is not used with basic authentication, given it is often - not used with HttpSessions. Remember-me is used with - UsernamePasswordAuthenticationFilter, and is implemented via hooks in - the AbstractAuthenticationProcessingFilter superclass. The hooks will - invoke a concrete RememberMeServices at the appropriate - times. The interface looks like this: - - Authentication autoLogin(HttpServletRequest request, HttpServletResponse response); - void loginFail(HttpServletRequest request, HttpServletResponse response); - void loginSuccess(HttpServletRequest request, HttpServletResponse response, - Authentication successfulAuthentication); - - Please refer to the JavaDocs for a fuller discussion on what the methods do, although - note at this stage that AbstractAuthenticationProcessingFilter only - calls the loginFail() and loginSuccess() methods. - The autoLogin() method is called by - RememberMeAuthenticationFilter whenever the - SecurityContextHolder does not contain an - Authentication. This interface therefore provides the - underlying remember-me implementation with sufficient notification of - authentication-related events, and delegates to the implementation whenever a candidate - web request might contain a cookie and wish to be remembered. This design allows any - number of remember-me implementation strategies. We've seen above that Spring Security - provides two implementations. We'll look at these in turn. -
- TokenBasedRememberMeServices - This implementation supports the simpler approach described in . - TokenBasedRememberMeServices generates a - RememberMeAuthenticationToken, which is processed by - RememberMeAuthenticationProvider. A key is - shared between this authentication provider and the - TokenBasedRememberMeServices. In addition, - TokenBasedRememberMeServices requires A UserDetailsService from - which it can retrieve the username and password for signature comparison purposes, - and generate the RememberMeAuthenticationToken to contain the - correct GrantedAuthoritys. Some sort of logout - command should be provided by the application that invalidates the cookie if the - user requests this. TokenBasedRememberMeServices also - implements Spring Security's LogoutHandler interface - so can be used with LogoutFilter to have the cookie cleared - automatically. - The beans required in an application context to enable remember-me services are as - follows: - - - - - - - - - - - - -]]> - Don't forget to add your - RememberMeServices implementation to your - UsernamePasswordAuthenticationFilter.setRememberMeServices() - property, include the RememberMeAuthenticationProvider in your - AuthenticationManager.setProviders() list, and add - RememberMeAuthenticationFilter into your - FilterChainProxy (typically immediately after your - UsernamePasswordAuthenticationFilter). -
-
- PersistentTokenBasedRememberMeServices - This class can be used in the same way as - TokenBasedRememberMeServices, but it additionally needs to be - configured with a PersistentTokenRepository to store - the tokens. There are two standard implementations. - - InMemoryTokenRepositoryImpl which is intended for - testing only. - - - JdbcTokenRepositoryImpl which stores the tokens in - a database. - - The database schema is described above in . -
-
-
diff --git a/docs/manual/src/docbook/runas-auth-provider.xml b/docs/manual/src/docbook/runas-auth-provider.xml deleted file mode 100644 index 594906bb81..0000000000 --- a/docs/manual/src/docbook/runas-auth-provider.xml +++ /dev/null @@ -1,97 +0,0 @@ - - - Run-As Authentication Replacement - - -
- - Overview - - - The AbstractSecurityInterceptor is able to temporarily replace - the Authentication object in the - SecurityContext and - SecurityContextHolder during the secure object callback phase. - This only occurs if the original Authentication object - was successfully processed by the AuthenticationManager - and AccessDecisionManager. The - RunAsManager will indicate the replacement - Authentication object, if any, that should be used during - the SecurityInterceptorCallback. - - By temporarily replacing the Authentication object - during the secure object callback phase, the secured invocation will be able to call - other objects which require different authentication and authorization credentials. It - will also be able to perform any internal security checks for specific - GrantedAuthority objects. Because Spring Security - provides a number of helper classes that automatically configure remoting protocols - based on the contents of the SecurityContextHolder, these run-as - replacements are particularly useful when calling remote web services -
- -
- - Configuration - - A RunAsManager interface is provided by Spring Security: - - Authentication buildRunAs(Authentication authentication, Object object, - List<ConfigAttribute> config); - boolean supports(ConfigAttribute attribute); - boolean supports(Class clazz); - - - The first method returns the Authentication object that - should replace the existing Authentication object for the - duration of the method invocation. If the method returns null, it - indicates no replacement should be made. The second method is used by the - AbstractSecurityInterceptor as part of its startup validation of - configuration attributes. The supports(Class) method is called by a - security interceptor implementation to ensure the configured - RunAsManager supports the type of secure object that the security - interceptor will present. - - One concrete implementation of a RunAsManager is provided with - Spring Security. The RunAsManagerImpl class returns a replacement - RunAsUserToken if any ConfigAttribute starts with - RUN_AS_. If any such ConfigAttribute is found, the - replacement RunAsUserToken will contain the same principal, - credentials and granted authorities as the original - Authentication object, along with a new - GrantedAuthorityImpl for each RUN_AS_ - ConfigAttribute. Each new GrantedAuthorityImpl - will be prefixed with ROLE_, followed by the - RUN_AS ConfigAttribute. For example, a - RUN_AS_SERVER will result in the replacement - RunAsUserToken containing a ROLE_RUN_AS_SERVER - granted authority. - - The replacement RunAsUserToken is just like any other - Authentication object. It needs to be authenticated by - the AuthenticationManager, probably via delegation to a - suitable AuthenticationProvider. The - RunAsImplAuthenticationProvider performs such authentication. It - simply accepts as valid any RunAsUserToken presented. - - To ensure malicious code does not create a RunAsUserToken and - present it for guaranteed acceptance by the - RunAsImplAuthenticationProvider, the hash of a key is stored in all - generated tokens. The RunAsManagerImpl and - RunAsImplAuthenticationProvider is created in the bean context with - the same key: - - - - - - -]]> - By using the same key, each RunAsUserToken can be validated it was - created by an approved RunAsManagerImpl. The - RunAsUserToken is immutable after creation for security - reasons -
-
diff --git a/docs/manual/src/docbook/samples.xml b/docs/manual/src/docbook/samples.xml deleted file mode 100644 index 6138476d72..0000000000 --- a/docs/manual/src/docbook/samples.xml +++ /dev/null @@ -1,145 +0,0 @@ - - - Sample Applications - - There are several sample web applications that are available with the project. To avoid - an overly large download, only the "tutorial" and "contacts" samples are included in the - distribution zip file. The others can be built directly from the source which you can obtain - as described in the introduction. It's easy to build - the project yourself and there's more information on the project web site at - http://www.springsource.org/security/ . All paths referred to in this chapter are - relative to the project source directory. -
- Tutorial Sample - The tutorial sample is a nice basic example to get you started. It uses simple - namespace configuration throughout. The compiled application is included in the - distribution zip file, ready to be deployed into your web container - (spring-security-samples-tutorial-3.1.x.war). The form-based authentication mechanism is used in - combination with the commonly-used remember-me - authentication provider to automatically remember the login using cookies. - We recommend you start with the tutorial sample, as the XML is minimal and easy to - follow. Most importantly, you can easily add this one XML file (and its corresponding - web.xml entries) to your existing application. Only when this basic - integration is achieved do we suggest you attempt adding in method authorization or - domain object security. -
-
- Contacts - The Contacts Sample is an advanced example in that it illustrates the more powerful - features of domain object access control lists (ACLs) in addition to basic application - security. The application provides an interface with which the users are able to - administer a simple database of contacts (the domain objects). - To deploy, simply copy the WAR file from Spring Security distribution into your - container’s webapps directory. The war should be called - spring-security-samples-contacts-3.1.x.war (the appended version - number will vary depending on what release you are using). - After starting your container, check the application can load. Visit - http://localhost:8080/contacts (or whichever URL is appropriate for - your web container and the WAR you deployed). - Next, click "Debug". You will be prompted to authenticate, and a series of usernames - and passwords are suggested on that page. Simply authenticate with any of these and view - the resulting page. It should contain a success message similar to the following: - -Security Debug Information - -Authentication object is of type: -org.springframework.security.authentication.UsernamePasswordAuthenticationToken - -Authentication object as a String: - -org.springframework.security.authentication.UsernamePasswordAuthenticationToken@1f127853: -Principal: org.springframework.security.core.userdetails.User@b07ed00: Username: rod; \ -Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; -credentialsNonExpired: true; AccountNonLocked: true; \ -Granted Authorities: ROLE_SUPERVISOR, ROLE_USER; \ -Password: [PROTECTED]; Authenticated: true; \ -Details: org.springframework.security.web.authentication.WebAuthenticationDetails@0: \ -RemoteIpAddress: 127.0.0.1; SessionId: 8fkp8t83ohar; \ -Granted Authorities: ROLE_SUPERVISOR, ROLE_USER - -Authentication object holds the following granted authorities: - -ROLE_SUPERVISOR (getAuthority(): ROLE_SUPERVISOR) -ROLE_USER (getAuthority(): ROLE_USER) - -Success! Your web filters appear to be properly configured! - - Once you successfully receive the above message, return to the sample application's - home page and click "Manage". You can then try out the application. Notice that only the - contacts available to the currently logged on user are displayed, and only users with - ROLE_SUPERVISOR are granted access to delete their contacts. Behind - the scenes, the MethodSecurityInterceptor is securing the - business objects. - The application allows you to modify the access control lists associated with - different contacts. Be sure to give this a try and understand how it works by reviewing - the application context XML files. - -
-
- LDAP Sample - The LDAP sample application provides a basic configuration and sets up both a - namespace configuration and an equivalent configuration using traditional beans, both in - the same application context file. This means there are actually two identical - authentication providers configured in this application. -
-
- OpenID Sample - - The OpenID sample demonstrates how to use the namespace to configure OpenID and how to set up - attribute exchange - configurations for Google, Yahoo and MyOpenID identity providers (you can experiment with adding others - if you wish). It uses the JQuery-based openid-selector - project to provide a user-friendly login page which allows the user to easily select a provider, rather than - typing in the full OpenID identifier. - - - The application differs from normal authentication scenarios in that it allows any user to access the site (provided - their OpenID authentication is successful). The first time you login, you will get a Welcome [your name]" - message. If you logout and log back in (with the same OpenID identity) then this should change to Welcome Back. - This is achieved by using a custom UserDetailsService which assigns a standard role - to any user and stores the identities internally in a map. Obviously a real application would use a database instead. - Have a look at the source form more information. This class also takes into account the fact that different attributes may be returned - from different providers and builds the name with which it addresses the user accordingly. - -
-
- CAS Sample - The CAS sample requires that you run both a CAS server and CAS client. It isn't - included in the distribution so you should check out the project code as described in - the introduction. You'll find the relevant files - under the sample/cas directory. There's also a - Readme.txt file in there which explains how to run both the server - and the client directly from the source tree, complete with SSL support. -
-
- JAAS Sample - The JAAS sample is very simple example of how to use a JAAS LoginModule with Spring Security. The provided LoginModule will - successfully authenticate a user if the username equals the password otherwise a LoginException is thrown. The AuthorityGranter - used in this example always grants the role ROLE_USER. The sample application also demonstrates how to run as the JAAS Subject - returned by the LoginModule by setting jaas-api-provision equal to "true". -
-
- Pre-Authentication Sample - This sample application demonstrates how to wire up beans from the pre-authentication framework to make use of login - information from a J2EE container. The user name and roles are those setup by the - container. - The code is in samples/preauth. -
-
diff --git a/docs/manual/src/docbook/secured-objects.xml b/docs/manual/src/docbook/secured-objects.xml deleted file mode 100644 index b25e779615..0000000000 --- a/docs/manual/src/docbook/secured-objects.xml +++ /dev/null @@ -1,154 +0,0 @@ - - - Secure Object Implementations - -
- - AOP Alliance (MethodInvocation) Security Interceptor - - Prior to Spring Security 2.0, securing MethodInvocations - needed quite a lot of boiler plate configuration. Now the recommended approach for - method security is to use namespace - configuration. This way the method security infrastructure beans are configured - automatically for you so you don't really need to know about the implementation classes. - We'll just provide a quick overview of the classes that are involved here. - Method security in enforced using a MethodSecurityInterceptor, - which secures MethodInvocations. Depending on the configuration - approach, an interceptor may be specific to a single bean or shared between multiple - beans. The interceptor uses a - MethodSecurityMetadataSource instance to obtain the - configuration attributes that apply to a particular method invocation. - MapBasedMethodSecurityMetadataSource is used to store - configuration attributes keyed by method names (which can be wildcarded) and will be - used internally when the attributes are defined in the application context using the - <intercept-methods> or <protect-point> - elements. Other implementations will be used to handle annotation-based configuration. -
- Explicit MethodSecurityInterceptor Configuration - You can of course configure a MethodSecurityIterceptor - directly in your application context for use with one of Spring AOP's proxying - mechanisms: - - - - - - - - - - ]]> - -
-
-
- - AspectJ (JoinPoint) Security Interceptor - - The AspectJ security interceptor is very similar to the AOP Alliance security - interceptor discussed in the previous section. Indeed we will only discuss the - differences in this section. - The AspectJ interceptor is named AspectJSecurityInterceptor. Unlike - the AOP Alliance security interceptor, which relies on the Spring application context to - weave in the security interceptor via proxying, the - AspectJSecurityInterceptor is weaved in via the AspectJ compiler. It - would not be uncommon to use both types of security interceptors in the same - application, with AspectJSecurityInterceptor being used for domain - object instance security and the AOP Alliance - MethodSecurityInterceptor being used for services layer - security. - Let's first consider how the AspectJSecurityInterceptor is - configured in the Spring application context: - - - - - - - - - - -]]> - As you can see, aside from the class name, the - AspectJSecurityInterceptor is exactly the same as the AOP Alliance - security interceptor. Indeed the two interceptors can share the same - securityMetadataSource, as the - SecurityMetadataSource works with - java.lang.reflect.Methods rather than an AOP library-specific class. - Of course, your access decisions have access to the relevant AOP library-specific - invocation (ie MethodInvocation or JoinPoint) - and as such can consider a range of addition criteria when making access decisions (such - as method arguments). - Next you'll need to define an AspectJ aspect. For example: - -package org.springframework.security.samples.aspectj; - -import org.springframework.security.access.intercept.aspectj.AspectJSecurityInterceptor; -import org.springframework.security.access.intercept.aspectj.AspectJCallback; -import org.springframework.beans.factory.InitializingBean; - -public aspect DomainObjectInstanceSecurityAspect implements InitializingBean { - - private AspectJSecurityInterceptor securityInterceptor; - - pointcut domainObjectInstanceExecution(): target(PersistableEntity) - && execution(public * *(..)) && !within(DomainObjectInstanceSecurityAspect); - - Object around(): domainObjectInstanceExecution() { - if (this.securityInterceptor == null) { - return proceed(); - } - - AspectJCallback callback = new AspectJCallback() { - public Object proceedWithObject() { - return proceed(); - } - }; - - return this.securityInterceptor.invoke(thisJoinPoint, callback); - } - - public AspectJSecurityInterceptor getSecurityInterceptor() { - return securityInterceptor; - } - - public void setSecurityInterceptor(AspectJSecurityInterceptor securityInterceptor) { - this.securityInterceptor = securityInterceptor; - } - - public void afterPropertiesSet() throws Exception { - if (this.securityInterceptor == null) - throw new IllegalArgumentException("securityInterceptor required"); - } - } -} - - In the above example, the security interceptor will be applied to every instance of - PersistableEntity, which is an abstract class not shown (you can use - any other class or pointcut expression you like). For those curious, - AspectJCallback is needed because the proceed(); - statement has special meaning only within an around() body. The - AspectJSecurityInterceptor calls this anonymous - AspectJCallback class when it wants the target object to - continue. - You will need to configure Spring to load the aspect and wire it with the - AspectJSecurityInterceptor. A bean declaration which achieves this is - shown below: - - -]]> - - That's it! Now you can create your beans from anywhere within your application, using - whatever means you think fit (eg new Person();) and they will have - the security interceptor applied. -
-
diff --git a/docs/manual/src/docbook/security-filter-chain.xml b/docs/manual/src/docbook/security-filter-chain.xml deleted file mode 100644 index 12e3c7686e..0000000000 --- a/docs/manual/src/docbook/security-filter-chain.xml +++ /dev/null @@ -1,338 +0,0 @@ - - - The Security Filter Chain - - Spring Security's web infrastructure is based entirely on standard servlet filters. It - doesn't use servlets or any other servlet-based frameworks (such as Spring MVC) internally, - so it has no strong links to any particular web technology. It deals in - HttpServletRequests and HttpServletResponses - and doesn't care whether the requests come from a browser, a web service client, an - HttpInvoker or an AJAX application. - Spring Security maintains a filter chain internally where each of the filters has a - particular responsibility and filters are added or removed from the configuration depending - on which services are required. The ordering of the filters is important as there are - dependencies between them. If you have been using namespace - configuration, then the filters are automatically configured for you and you don't - have to define any Spring beans explicitly but here may be times when you want full control - over the security filter chain, either because you are using features which aren't supported - in the namespace, or you are using your own customized versions of classes. -
- <classname>DelegatingFilterProxy</classname> - When using servlet filters, you obviously need to declare them in your - web.xml, or they will be ignored by the servlet container. In - Spring Security, the filter classes are also Spring beans defined in the application - context and thus able to take advantage of Spring's rich dependency-injection facilities - and lifecycle interfaces. Spring's DelegatingFilterProxy provides - the link between web.xml and the application context. - When using DelegatingFilterProxy, you will see something like - this in the web.xml file: - myFilter - org.springframework.web.filter.DelegatingFilterProxy - - - - myFilter - /* - ]]> - Notice that the filter is actually a - DelegatingFilterProxy, and not the class that will actually implement - the logic of the filter. What DelegatingFilterProxy does is - delegate the Filter's methods through to a bean which is - obtained from the Spring application context. This enables the bean to benefit from the - Spring web application context lifecycle support and configuration flexibility. The bean - must implement javax.servlet.Filter and it must have the - same name as that in the filter-name element. Read the Javadoc for - DelegatingFilterProxy for more information -
-
- <classname>FilterChainProxy</classname> - Spring Security's web infrastructure should only be used by delegating to an - instance of FilterChainProxy. The security filters should not - be used by themselves. In theory you could declare each Spring Security filter bean - that you require in your application context file and add a corresponding - DelegatingFilterProxy entry to web.xml - for each filter, making sure that they are ordered correctly, but this would be - cumbersome and would clutter up the web.xml file quickly if you - have a lot of filters. FilterChainProxy lets us add a single - entry to web.xml and deal entirely with the application context - file for managing our web security beans. It is wired using a - DelegatingFilterProxy, just like in the example above, but with - the filter-name set to the bean name - filterChainProxy. The filter chain is then declared in the application - context with the same bean name. Here's an example: - - - - - - - -]]> - The namespace element filter-chain is used for convenience - to set up the security filter chain(s) which are required within the application. - Note that you'll need to include the security namespace in your application - context XML file in order to use this syntax. The older syntax which used a - filter-chain-map is still supported, but is deprecated in favour of - the constructor argument injection. - . It maps a particular URL pattern to a list of filters built up from the - bean names specified in the filters element, and combines them in - a bean of type SecurityFilterChain. The pattern - attribute takes an Ant Paths and the most specific URIs should appear first - Instead of a path pattern, the request-matcher-ref attribute - can be used to specify a RequestMatcher instance for more powerful - matching. At runtime the FilterChainProxy will - locate the first URI pattern that matches the current web request and the list of filter beans - specified by the filters attribute will be applied to that request. - The filters will be invoked in the order they are defined, so you have complete control - over the filter chain which is applied to a particular URL. - You may have noticed we have declared two - SecurityContextPersistenceFilters in the filter chain - (ASC is short for allowSessionCreation, a property - of SecurityContextPersistenceFilter). As web services will never - present a jsessionid on future requests, creating - HttpSessions for such user agents would be wasteful. If you had a - high-volume application which required maximum scalability, we recommend you use the - approach shown above. For smaller applications, using a single - SecurityContextPersistenceFilter (with its default - allowSessionCreation as true) would likely be - sufficient. - Note that FilterChainProxy does not invoke standard filter - lifecycle methods on the filters it is configured with. We recommend you use - Spring's application context lifecycle interfaces as an alternative, just as you - would for any other Spring bean. - When we looked at how to set up web security using namespace configuration, we used a DelegatingFilterProxy with - the name springSecurityFilterChain. You should now be able to see that - this is the name of the FilterChainProxy which is created by the - namespace. -
- Bypassing the Filter Chain - You can use the attribute filters = - "none" as an alternative to supplying a filter bean list. This will omit - the request pattern from the security filter chain entirely. Note that anything - matching this path will then have no authentication or authorization services - applied and will be freely accessible. If you want to make use of the contents of - the SecurityContext contents during a request, then it must - have passed through the security filter chain. Otherwise the - SecurityContextHolder will not have been populated and the - contents will be null. -
-
-
- Filter Ordering - The order that filters are defined in the chain is very important. Irrespective of - which filters you are actually using, the order should be as follows: - - ChannelProcessingFilter, because it might need to - redirect to a different protocol - - - SecurityContextPersistenceFilter, so a - SecurityContext can be set up in the - SecurityContextHolder at the beginning of a web request, - and any changes to the SecurityContext can be - copied to the HttpSession when the web request ends (ready - for use with the next web request) - - - ConcurrentSessionFilter, because it uses the - SecurityContextHolder functionality and needs to update - the SessionRegistry to reflect ongoing requests - from the principal - - - Authentication processing mechanisms - - UsernamePasswordAuthenticationFilter, - CasAuthenticationFilter, - BasicAuthenticationFilter etc - so that the - SecurityContextHolder can be modified to contain a valid - Authentication request token - - - The SecurityContextHolderAwareRequestFilter, if you are - using it to install a Spring Security aware - HttpServletRequestWrapper into your servlet container - - - The JaasApiIntegrationFilter, if a - JaasAuthenticationToken is in the - SecurityContextHolder this will process the - FilterChain as the Subject in the - JaasAuthenticationToken - - - RememberMeAuthenticationFilter, so that if no earlier - authentication processing mechanism updated the - SecurityContextHolder, and the request presents a cookie - that enables remember-me services to take place, a suitable remembered - Authentication object will be put there - - - AnonymousAuthenticationFilter, so that if no earlier - authentication processing mechanism updated the - SecurityContextHolder, an anonymous - Authentication object will be put there - - - ExceptionTranslationFilter, to catch any Spring - Security exceptions so that either an HTTP error response can be returned or an - appropriate AuthenticationEntryPoint can be - launched - - - FilterSecurityInterceptor, to protect web URIs and - raise exceptions when access is denied - - -
-
- Request Matching and <interfacename>HttpFirewall</interfacename> - Spring Security has several areas where patterns you have defined are tested - against incoming requests in order to decide how the request should be handled. This - occurs when the FilterChainProxy decides which filter chain a - request should be passed through and also when the - FilterSecurityInterceptor decides which security constraints - apply to a request. It's important to understand what the mechanism is and what URL - value is used when testing against the patterns that you define. - The Servlet Specification defines several properties for the - HttpServletRequest which are accessible via getter - methods, and which we might want to match against. These are the - contextPath, servletPath, - pathInfo and queryString. Spring Security is - only interested in securing paths within the application, so the - contextPath is ignored. Unfortunately, the servlet spec does not - define exactly what the values of servletPath and - pathInfo will contain for a particular request URI. For example, - each path segment of a URL may contain parameters, as defined in RFC 2396 - You have probably seen this when a browser doesn't support cookies and the - jsessionid parameter is appended to the URL after a - semi-colon. However the RFC allows the presence of these parameters in any path - segment of the URL - . The Specification does not clearly state whether these should be - included in the servletPath and pathInfo - values and the behaviour varies between different servlet containers. There is a - danger that when an application is deployed in a container which does not strip path - parameters from these values, an attacker could add them to the requested URL in - order to cause a pattern match to succeed or fail unexpectedly. - The original values will be returned once the request leaves the - FilterChainProxy, so will still be available to the - application. - . Other variations in the incoming URL are also possible. For example, it - could contain path-traversal sequences (like /../) or multiple - forward slashes (//) which could also cause pattern-matches to - fail. Some containers normalize these out before performing the servlet mapping, but - others don't. To protect against issues like these, - FilterChainProxy uses an - HttpFirewall strategy to check and wrap the request. - Un-normalized requests are automatically rejected by default, and path parameters - and duplicate slashes are removed for matching purposes. - So, for example, an original request path - /secure;hack=1/somefile.html;hack=2 will be returned as - /secure/somefile.html. - . It is therefore essential that a - FilterChainProxy is used to manage the security filter chain. - Note that the servletPath and pathInfo values - are decoded by the container, so your application should not have any valid paths - which contain semi-colons, as these parts will be removed for matching purposes. - As mentioned above, the default strategy is to use Ant-style paths for matching - and this is likely to be the best choice for most users. The strategy is implemented - in the class AntPathRequestMatcher which uses Spring's - AntPathMatcher to perform a case-insensitive match of the - pattern against the concatenated servletPath and - pathInfo, ignoring the queryString. - If for some reason, you need a more powerful matching strategy, you can use - regular expressions. The strategy implementation is then - RegexRequestMatcher. See the Javadoc for this class for more - information. - In practice we recommend that you use method security at your service layer, to - control access to your application, and do not rely entirely on the use of security - constraints defined at the web-application level. URLs change and it is difficult to - take account of all the possible URLs that an application might support and how - requests might be manipulated. You should try and restrict yourself to using a few - simple ant paths which are simple to understand. Always try to use a - deny-by-default approach where you have a catch-all wildcard - (/** or **) defined last and denying access. - Security defined at the service layer is much more robust and harder to bypass, so - you should always take advantage of Spring Security's method security - options. -
-
- Use with other Filter-Based Frameworks - If you're using some other framework that is also filter-based, then you need to make - sure that the Spring Security filters come first. This enables the - SecurityContextHolder to be populated in time for use by the - other filters. Examples are the use of SiteMesh to decorate your web pages or a web - framework like Wicket which uses a filter to handle its requests. -
-
- Advanced Namespace Configuration - As we saw earlier in the namespace chapter, it's possible to use multiple http - elements to define different security configurations for different URL patterns. - Each element creates a filter chain within the internal FilterChainProxy and the - URL pattern that should be mapped to it. The elements will be added in the order they are declared, so the - most specific patterns must again be declared first. Here's another example, for a similar situation to - that above, where the application supports both a stateless RESTful API and also a normal web application - which users log into using a form. - - - - - - - - - - - - - - - - - ]]> - - -
- -
diff --git a/docs/manual/src/docbook/servlet-api.xml b/docs/manual/src/docbook/servlet-api.xml deleted file mode 100644 index fa810ef58e..0000000000 --- a/docs/manual/src/docbook/servlet-api.xml +++ /dev/null @@ -1,167 +0,0 @@ - - - Servlet API integration - - This section describes how Spring Security is integrated with the Servlet API. The - servletapi-xml sample application demonstrates - the usage of each of these methods. -
- Servlet 2.5+ Integration -
- HttpServletRequest.getRemoteUser() - The HttpServletRequest.getRemoteUser() - will return the result of SecurityContextHolder.getContext().getAuthentication().getName() which is typically the current - username. This can be useful if you want to display the current username in your application. Additionally, checking if this - is null can be used to indicate if a user has authenticated or is anonymous. Knowing if the user is authenticated or not can - be useful for determining if certain UI elements should be shown or not (i.e. a log out link should only be displayed if the - user is authenticated). -
-
- HttpServletRequest.getUserPrincipal() - The HttpServletRequest.getUserPrincipal() - will return the result of SecurityContextHolder.getContext().getAuthentication(). This means it is an Authentication - which is typically an instance of UsernamePasswordAuthenticationToken when using username and password based authentication. This can be useful if - you need additional information about your user. For example, you might have created a custom UserDetailsService - that returns a custom UserDetails containing a first and last name for your user. You could obtain this information with the - following: - - - It should be noted that it is typically bad practice to perform so much logic throughout your application. Instead, one should centralize it to reduce - any coupling of Spring Security and the Servlet API's. - - -
-
- HttpServletRequest.isUserInRole(String) - The HttpServletRequest.isUserInRole(String) - will determine if SecurityContextHolder.getContext().getAuthentication().getAuthorities() contains a - GrantedAuthority with the role passed into isUserInRole(String). Typically users should not pass in the "ROLE_" prefix - into this method since it is added automatically. For example, if you want to determine if the current user has the authority "ROLE_ADMIN", you could use the - the following: - - This might be useful to determine if certain UI components should be displayed. For example, you might display admin links only if the current - user is an admin. -
-
-
- Servlet 3+ Integration - The following section describes the Servlet 3 methods that Spring Security integrates with. -
- HttpServletRequest.authenticate(HttpServletRequest,HttpServletResponse) - The HttpServletRequest.authenticate(HttpServletRequest,HttpServletResponse) - method can be used to ensure that a user is authenticated. If they are not authenticated, the configured AuthenticationEntryPoint will be used to request the user to authenticate - (i.e. redirect to the login page). -
-
- HttpServletRequest.login(String,String) - The HttpServletRequest.login(String,String) - method can be used to authenticate the user with the current AuthenticationManager. For example, the following would attempt to - authenticate with the username "user" and password "password": - - - It is not necessary to catch the ServletException if you want Spring Security to process the failed authentication attempt. - -
-
- HttpServletRequest.logout() - The HttpServletRequest.logout() - method can be used to log the current user out. - Typically this means that the SecurityContextHolder will be cleared out, the HttpSession will be invalidated, any "Remember Me" authentication will be - cleaned up, etc. However, the configured LogoutHandler implementations will vary depending on your Spring Security configuration. It is important to note - that after HttpServletRequest.logout() has been invoked, you are still in charge of writing a response out. Typically this would involve a redirect to the - welcome page. -
-
- AsyncContext.start(Runnable) - The AsynchContext.start(Runnable) - method that ensures your credentials will be propagated to the new Thread. Using Spring Security's concurrency support, Spring Security overrides - the AsyncContext.start(Runnable) to ensure that the current SecurityContext is used when processing the Runnable. For example, the following - would output the current user's Authentication: - -
-
- Async Servlet Support - If you are using Java Based configuration, you are ready to go. If you are using XML configuration, there are - a few updates that are necessary. The first step is to ensure you have updated your web.xml to use at least the 3.0 schema - as shown below: - - -]]> - Next you need to ensure that your springSecurityFilterChain is setup for processing asynchronous requests. - - springSecurityFilterChain - - org.springframework.web.filter.DelegatingFilterProxy - - true - - - springSecurityFilterChain - /* - REQUEST - ASYNC -]]> - That's it! Now Spring Security will ensure that your SecurityContext is propagated on asynchronous requests too. - So how does it work? If you are not really interested, feel free to skip the remainder of this section, otherwise read on. Most of this - is built into the Servlet specification, but there is a little bit of tweaking that Spring Security does to ensure things work with - asynchronous requests properly. Prior to Spring Security 3.2, the SecurityContext from the SecurityContextHolder was automatically saved as soon - as the HttpServletResponse was committed. This can cause issues in a Async environment. For example, consider the following: - - The issue is that this Thread is not known to Spring Security, so the SecurityContext is not propagated to it. This means when we commit the - HttpServletResponse there is no SecuriytContext. When Spring Security automatically saved the SecurityContext on committing the HttpServletResponse it - would lose our logged in user. - Since version 3.2, Spring Security is smart enough to no longer automatically save the SecurityContext on commiting the HttpServletResponse - as soon as HttpServletRequest.startAsync() is invoked. -
-
-
- Servlet 3.1+ Integration - The following section describes the Servlet 3.1 methods that Spring Security integrates with. -
- HttpServletRequest#changeSessionId() - The HttpServletRequest.changeSessionId() - is the default method for protecting against Session Fixation attacks in Servlet 3.1 and higher. -
-
-
diff --git a/docs/manual/src/docbook/session-mgmt.xml b/docs/manual/src/docbook/session-mgmt.xml deleted file mode 100644 index bff3c464c6..0000000000 --- a/docs/manual/src/docbook/session-mgmt.xml +++ /dev/null @@ -1,181 +0,0 @@ - - - Session Management - - HTTP session related functonality is handled by a combination of the - SessionManagementFilter and the - SessionAuthenticationStrategy interface, which the filter - delegates to. Typical usage includes session-fixation protection attack prevention, - detection of session timeouts and restrictions on how many sessions an authenticated user - may have open concurrently. -
- SessionManagementFilter - The SessionManagementFilter checks the contents of the - SecurityContextRepository against the current contents of - the SecurityContextHolder to determine whether a user has been - authenticated during the current request, typically by a non-interactive authentication - mechanism, such as pre-authentication or remember-me - Authentication by mechanisms which perform a redirect after authenticating (such - as form-login) will not be detected by - SessionManagementFilter, as the filter will not be invoked - during the authenticating request. Session-management functionality has to be - handled separately in these cases. - . If the repository contains a security context, the filter does nothing. If - it doesn't, and the thread-local SecurityContext contains - a (non-anonymous) Authentication object, the filter - assumes they have been authenticated by a previous filter in the stack. It will then - invoke the configured - SessionAuthenticationStrategy. - If the user is not currently authenticated, the filter will check whether an invalid - session ID has been requested (because of a timeout, for example) and will invoke the configured - InvalidSessionStrategy, if one is set. The most common behaviour - is just to redirect to a fixed URL and this is encapsulated in the standard implementation - SimpleRedirectInvalidSessionStrategy. The latter is also used - when configuring an invalid session URL through the namespace, - as described earlier. -
-
- <interfacename>SessionAuthenticationStrategy</interfacename> - SessionAuthenticationStrategy is used by both - SessionManagementFilter and - AbstractAuthenticationProcessingFilter, so if you are using a - customized form-login class, for example, you will need to inject it into both of these. - In this case, a typical configuration, combining the namespace and custom beans might - look like this: - - - - - - - ... - - - -]]> - Note that the use of the default, SessionFixationProtectionStrategy - may cause issues if you are storing beans in the session which implement - HttpSessionBindingListener, including Spring session-scoped - beans. See the Javadoc for this class for more information. - -
-
- Concurrency Control - Spring Security is able to prevent a principal from concurrently authenticating to the - same application more than a specified number of times. Many ISVs take advantage of this - to enforce licensing, whilst network administrators like this feature because it helps - prevent people from sharing login names. You can, for example, stop user - Batman from logging onto the web application from two different sessions. - You can either expire their previous login or you can report an error when they try to - log in again, preventing the second login. Note that if you are using the second - approach, a user who has not explicitly logged out (but who has just closed their - browser, for example) will not be able to log in again until their original session - expires. - Concurrency control is supported by the namespace, so please check the earlier - namespace chapter for the simplest configuration. Sometimes you need to customize things - though. - The implementation uses a specialized version of - SessionAuthenticationStrategy, called - ConcurrentSessionControlAuthenticationStrategy. - Previously the concurrent authentication check was made by the - ProviderManager, which could be injected with a - ConcurrentSessionController. The latter would check if the user - was attempting to exceed the number of permitted sessions. However, this approach - required that an HTTP session be created in advance, which is undesirable. In Spring - Security 3, the user is first authenticated by the - AuthenticationManager and once they are successfully - authenticated, a session is created and the check is made whether they are allowed - to have another session open. - - To use concurrent session support, you'll need to add the following to - web.xml: - - org.springframework.security.web.session.HttpSessionEventPublisher - - ]]> - - In addition, you will need to add the ConcurrentSessionFilter to - your FilterChainProxy. The - ConcurrentSessionFilter requires two properties, - sessionRegistry, which generally points to an instance of - SessionRegistryImpl, and expiredUrl, which - points to the page to display when a session has expired. A configuration using the - namespace to create the FilterChainProxy and other default beans - might look like this: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -]]> - - Adding the listener to web.xml causes an - ApplicationEvent to be published to the Spring - ApplicationContext every time a HttpSession - commences or terminates. This is critical, as it allows the - SessionRegistryImpl to be notified when a session ends. Without - it, a user will never be able to log back in again once they have exceeded their session - allowance, even if they log out of another session or it times out. -
- Querying the <interfacename>SessionRegistry</interfacename> for currently authenticated - users and their sessions - - Setting up concurrency-control, either through the namespace or using plain beans has the - useful side effect of providing you with a reference to the SessionRegistry - which you can use directly within your application, so even if you don't want to restrict the - number of sessions a user may have, it may be worth setting up the infrastructure anyway. You can - set the maximumSession property to -1 to allow unlimited sessions. If - you're using the namespace, you can set an alias for the internally-created - SessionRegistry using the session-registry-alias - attribute, providing a reference which you can inject into your own beans. - - The getAllPrincipals() - method supplies you with a list of the currently authenticated users. You can list a user's - sessions by calling the getAllSessions(Object principal, boolean includeExpiredSessions) method, - which returns a list of SessionInformation objects. You can also - expire a user's session by calling expireNow() on a - SessionInformation instance. When the user returns to the application, they - will be prevented from proceeding. You may find these methods useful in an administration - application, for example. Have a look at the Javadoc for more information. - -
-
-
diff --git a/docs/manual/src/docbook/taglibs.xml b/docs/manual/src/docbook/taglibs.xml deleted file mode 100644 index 1ab1830c32..0000000000 --- a/docs/manual/src/docbook/taglibs.xml +++ /dev/null @@ -1,117 +0,0 @@ - - JSP Tag Libraries - Spring Security has its own taglib which provides basic support for accessing security - information and applying security constraints in JSPs. -
- Declaring the Taglib - To use any of the tags, you must have the security taglib declared in your JSP: - - ]]> - -
-
- The <literal>authorize</literal> Tag - This tag is used to determine whether its contents should be evaluated or not. In - Spring Security 3.0, it can be used in two ways - The legacy options from Spring Security 2.0 are also supported, but - discouraged. - . The first approach uses a web-security - expression, specified in the access attribute of the tag. The - expression evaluation will be delegated to the - SecurityExpressionHandler<FilterInvocation> defined in the application - context (you should have web expressions enabled in your <http> - namespace configuration to make sure this service is available). So, for example, you - might - have<sec:authorize access="hasRole('supervisor')"> - -This content will only be visible to users who have -the "supervisor" authority in their list of <tt>GrantedAuthority</tt>s. - -</sec:authorize> - A common requirement is to only show a particular link, if the user is actually - allowed to click it. How can we determine in advance whether something will be allowed? - This tag can also operate in an alternative mode which allows you to define a particular - URL as an attribute. If the user is allowed to invoke that URL, then the tag body will - be evaluated, otherwise it will be skipped. So you might have something - like<sec:authorize url="/admin"> - -This content will only be visible to users who are authorized to send requests to the "/admin" URL. - -</sec:authorize>To - use this tag there must also be an instance of - WebInvocationPrivilegeEvaluator in your application - context. If you are using the namespace, one will automatically be registered. This is - an instance of DefaultWebInvocationPrivilegeEvaluator, which - creates a dummy web request for the supplied URL and invokes the security interceptor to - see whether the request would succeed or fail. This allows you to delegate to the - access-control setup you defined using intercept-url declarations - within the <http> namespace configuration and saves having to - duplicate the information (such as the required roles) within your JSPs. This approach - can also be combined with a method attribute, supplying the HTTP - method, for a more specific match. - The boolean result of evaluating the tag (whether it grants or denies access) can be - stored in a page context scope variable by setting the var attribute - to the variable name, avoiding the need for duplicating and re-evaluating the condition - at other points in the page. -
- Disabling Tag Authorization for Testing - Hiding a link in a page for unauthorized users doesn't prevent them from accessing - the URL. They could just type it into their browser directly, for example. As part - of your testing process, you may want to reveal the hidden areas in order to check - that links really are secured at the back end. If you set the system property - spring.security.disableUISecurity to true, - the authorize tag will still run but will not hide its contents. - By default it will also surround the content with <span - class="securityHiddenUI">...</span> tags. This allows you to - display hidden content with a particular CSS style such as a - different background colour. Try running the tutorial sample - application with this property enabled, for example. - You can also set the properties spring.security.securedUIPrefix - and spring.security.securedUISuffix if you want to change - surrounding text from the default span tags (or use empty strings - to remove it completely). -
-
-
- The <literal>authentication</literal>Tag - This tag allows access to the current Authentication - object stored in the security context. It renders a property of the object directly in - the JSP. So, for example, if the principal property of the - Authentication is an instance of Spring Security's - UserDetails object, then using - <sec:authentication property="principal.username" /> will render - the name of the current user. - Of course, it isn't necessary to use JSP tags for this kind of thing and some people - prefer to keep as little logic as possible in the view. You can access the - Authentication object in your MVC controller (by calling - SecurityContextHolder.getContext().getAuthentication()) and add the data - directly to your model for rendering by the view. -
-
- The <literal>accesscontrollist</literal> Tag - This tag is only valid when used with Spring Security's ACL module. It checks a - comma-separated list of required permissions for a specified domain object. If the - current user has any of those permissions, then the tag body will be evaluated. If they - don't, it will be skipped. An example might - be<sec:accesscontrollist hasPermission="1,2" domainObject="${someObject}"> - -This will be shown if the user has either of the permissions -represented by the values "1" or "2" on the given object. - -</sec:accesscontrollist> - The permissions are passed to the PermissionFactory - defined in the application context, converting them to ACL - Permission instances, so they may be any format which is - supported by the factory - they don't have to be integers, they could be strings like - READ or WRITE. If no - PermissionFactory is found, an instance of - DefaultPermissionFactory will be used. The - AclServicefrom the application context will be used to - load the Acl instance for the supplied object. The - Acl will be invoked with the required permissions to - check if any of them are granted. - This tag also supports the var attribute, in the same way as the - authorize tag. -
-
diff --git a/docs/manual/src/docbook/technical-overview.xml b/docs/manual/src/docbook/technical-overview.xml deleted file mode 100644 index d1c91ed040..0000000000 --- a/docs/manual/src/docbook/technical-overview.xml +++ /dev/null @@ -1,719 +0,0 @@ - - - Technical Overview - -
- - Runtime Environment - - Spring Security 3.0 requires a Java 5.0 Runtime Environment or higher. As Spring - Security aims to operate in a self-contained manner, there is no need to place any - special configuration files into your Java Runtime Environment. In particular, there is - no need to configure a special Java Authentication and Authorization Service (JAAS) - policy file or place Spring Security into common classpath locations. - Similarly, if you are using an EJB Container or Servlet Container there is no need to - put any special configuration files anywhere, nor include Spring Security in a server - classloader. All the required files will be contained within your application. - This design offers maximum deployment time flexibility, as you can simply copy your - target artifact (be it a JAR, WAR or EAR) from one system to another and it will - immediately work. -
-
- - Core Components - - In Spring Security 3.0, the contents of the spring-security-core - jar were stripped down to the bare minimum. It no longer contains any code related to - web-application security, LDAP or namespace configuration. We'll take a look here at - some of the Java types that you'll find in the core module. They represent the building - blocks of the the framework, so if you ever need to go beyond a simple namespace - configuration then it's important that you understand what they are, even if you don't - actually need to interact with them directly. -
- SecurityContextHolder, SecurityContext and Authentication Objects - The most fundamental object is SecurityContextHolder. This - is where we store details of the present security context of the application, which - includes details of the principal currently using the application. By default the - SecurityContextHolder uses a ThreadLocal - to store these details, which means that the security context is always available to - methods in the same thread of execution, even if the security context is not - explicitly passed around as an argument to those methods. Using a - ThreadLocal in this way is quite safe if care is taken to clear - the thread after the present principal's request is processed. Of course, Spring - Security takes care of this for you automatically so there is no need to worry about - it. - Some applications aren't entirely suitable for using a - ThreadLocal, because of the specific way they work with threads. - For example, a Swing client might want all threads in a Java Virtual Machine to use - the same security context. SecurityContextHolder can be - configured with a strategy on startup to specify how you would like the context to - be stored. For a standalone application you would use the - SecurityContextHolder.MODE_GLOBAL strategy. Other applications - might want to have threads spawned by the secure thread also assume the same - security identity. This is achieved by using - SecurityContextHolder.MODE_INHERITABLETHREADLOCAL. You can change - the mode from the default SecurityContextHolder.MODE_THREADLOCAL - in two ways. The first is to set a system property, the second is to call a static - method on SecurityContextHolder. Most applications won't need - to change from the default, but if you do, take a look at the JavaDocs for - SecurityContextHolder to learn more. -
- Obtaining information about the current user - Inside the SecurityContextHolder we store details of - the principal currently interacting with the application. Spring Security uses - an Authentication object to represent this - information. You won't normally need to create an - Authentication object yourself, but it is fairly - common for users to query the Authentication - object. You can use the following code block - from anywhere in your application - - to obtain the name of the currently authenticated user, for example: - -Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal(); - -if (principal instanceof UserDetails) { - String username = ((UserDetails)principal).getUsername(); -} else { - String username = principal.toString(); -} - The object returned by the call to getContext() is an - instance of the SecurityContext interface. This - is the object that is kept in thread-local storage. As we'll see below, most - authentication mechanisms withing Spring Security return an instance of - UserDetails as the principal. -
-
-
- The UserDetailsService - Another item to note from the above code fragment is that you can obtain a - principal from the Authentication object. The - principal is just an Object. Most of the time this can be cast - into a UserDetails object. - UserDetails is a core interface in Spring - Security. It represents a principal, but in an extensible and application-specific - way. Think of UserDetails as the adapter between your - own user database and what Spring Security needs inside the - SecurityContextHolder. Being a representation of something - from your own user database, quite often you will cast the - UserDetails to the original object that your - application provided, so you can call business-specific methods (like - getEmail(), getEmployeeNumber() and so - on). - By now you're probably wondering, so when do I provide a - UserDetails object? How do I do that? I thought you - said this thing was declarative and I didn't need to write any Java code - what - gives? The short answer is that there is a special interface called - UserDetailsService. The only method on this interface - accepts a String-based username argument and returns a - UserDetails: - - UserDetails loadUserByUsername(String username) throws UsernameNotFoundException; - - This is the most common approach to loading information for a user within Spring - Security and you will see it used throughout the framework whenever information on a - user is required. - On successful authentication, UserDetails is used - to build the Authentication object that is stored in - the SecurityContextHolder (more on this below). The good news is that we - provide a number of UserDetailsService - implementations, including one that uses an in-memory map - (InMemoryDaoImpl) and another that uses JDBC - (JdbcDaoImpl). Most users tend to write their own, though, - with their implementations often simply sitting on top of an existing Data Access - Object (DAO) that represents their employees, customers, or other users of the - application. Remember the advantage that whatever your - UserDetailsService returns can always be obtained - from the SecurityContextHolder using the above code fragment. - - - There is often some confusion about UserDetailsService. - It is purely a DAO for user data and performs no other function other than to supply that data - to other components within the framework. In particular, it does not - authenticate the user, which is done by the AuthenticationManager. - In many cases it makes more sense to - implement AuthenticationProvider - directly if you require a custom authentication process. - - -
-
- GrantedAuthority - Besides the principal, another important method provided by - Authentication is - getAuthorities(). This method provides an array of - GrantedAuthority objects. A - GrantedAuthority is, not surprisingly, an authority - that is granted to the principal. Such authorities are usually roles, - such as ROLE_ADMINISTRATOR or - ROLE_HR_SUPERVISOR. These roles are later on configured for web - authorization, method authorization and domain object authorization. Other parts of - Spring Security are capable of interpreting these authorities, and expect them to be - present. GrantedAuthority objects are usually loaded - by the UserDetailsService. - Usually the GrantedAuthority objects are - application-wide permissions. They are not specific to a given domain object. Thus, - you wouldn't likely have a GrantedAuthority to - represent a permission to Employee object number 54, because if - there are thousands of such authorities you would quickly run out of memory (or, at - the very least, cause the application to take a long time to authenticate a user). - Of course, Spring Security is expressly designed to handle this common requirement, - but you'd instead use the project's domain object security capabilities for this - purpose. -
-
- Summary - Just to recap, the major building blocks of Spring Security that we've seen so far - are: - - - SecurityContextHolder, to provide access to the - SecurityContext. - - - SecurityContext, to hold the - Authentication and possibly request-specific - security information. - - - Authentication, to represent the principal - in a Spring Security-specific manner. - - - GrantedAuthority, to reflect the - application-wide permissions granted to a principal. - - - UserDetails, to provide the necessary - information to build an Authentication object from your application's DAOs - or other source of security data. - - - UserDetailsService, to create a - UserDetails when passed in a - String-based username (or certificate ID or the - like). - - - Now that you've gained an understanding of these repeatedly-used components, let's - take a closer look at the process of authentication. -
-
-
- - Authentication - - Spring Security can participate in many different authentication environments. While - we recommend people use Spring Security for authentication and not integrate with - existing Container Managed Authentication, it is nevertheless supported - as is - integrating with your own proprietary authentication system. -
- What is authentication in Spring Security? - Let's consider a standard authentication scenario that everyone is familiar with. - - A user is prompted to log in with a username and password. - - - The system (successfully) verifies that the password is correct for the - username. - - - The context information for that user is obtained (their list of roles and - so on). - - - A security context is established for the user - - - The user proceeds, potentially to perform some operation which is - potentially protected by an access control mechanism which checks the - required permissions for the operation against the current security context - information. - - The first three items constitute the authentication process so we'll - take a look at how these take place within Spring Security. - - The username and password are obtained and combined into an instance of - UsernamePasswordAuthenticationToken (an instance of - the Authentication interface, which we saw - earlier). - - - The token is passed to an instance of - AuthenticationManager for validation. - - - The AuthenticationManager returns a fully - populated Authentication instance on - successful authentication. - - - The security context is established by calling - SecurityContextHolder.getContext().setAuthentication(...), - passing in the returned authentication object. - - From that point on, the user is considered to be authenticated. Let's - look at some code as an example. - import org.springframework.security.authentication.*; -import org.springframework.security.core.*; -import org.springframework.security.core.authority.SimpleGrantedAuthority; -import org.springframework.security.core.context.SecurityContextHolder; - -public class AuthenticationExample { - private static AuthenticationManager am = new SampleAuthenticationManager(); - - public static void main(String[] args) throws Exception { - BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); - - while(true) { - System.out.println("Please enter your username:"); - String name = in.readLine(); - System.out.println("Please enter your password:"); - String password = in.readLine(); - try { - Authentication request = new UsernamePasswordAuthenticationToken(name, password); - Authentication result = am.authenticate(request); - SecurityContextHolder.getContext().setAuthentication(result); - break; - } catch(AuthenticationException e) { - System.out.println("Authentication failed: " + e.getMessage()); - } - } - System.out.println("Successfully authenticated. Security context contains: " + - SecurityContextHolder.getContext().getAuthentication()); - } -} - -class SampleAuthenticationManager implements AuthenticationManager { - static final List<GrantedAuthority> AUTHORITIES = new ArrayList<GrantedAuthority>(); - - static { - AUTHORITIES.add(new SimpleGrantedAuthority("ROLE_USER")); - } - - public Authentication authenticate(Authentication auth) throws AuthenticationException { - if (auth.getName().equals(auth.getCredentials())) { - return new UsernamePasswordAuthenticationToken(auth.getName(), - auth.getCredentials(), AUTHORITIES); - } - throw new BadCredentialsException("Bad Credentials"); - } -}Here - we have written a little program that asks the user to enter a username and password - and performs the above sequence. The - AuthenticationManager which we've implemented here - will authenticate any user whose username and password are the same. It assigns a - single role to every user. The output from the above will be something - like: -Please enter your username: -bob -Please enter your password: -password -Authentication failed: Bad Credentials -Please enter your username: -bob -Please enter your password: -bob -Successfully authenticated. Security context contains: \ - org.springframework.security.authentication.UsernamePasswordAuthenticationToken@441d0230: \ - Principal: bob; Password: [PROTECTED]; \ - Authenticated: true; Details: null; \ - Granted Authorities: ROLE_USER - - Note that you don't normally need to write any code like this. The process will - normally occur internally, in a web authentication filter for example. We've just - included the code here to show that the question of what actually constitutes - authentication in Spring Security has quite a simple answer. A user is authenticated - when the SecurityContextHolder contains a fully populated - Authentication object. -
-
- Setting the SecurityContextHolder Contents Directly - In fact, Spring Security doesn't mind how you put the - Authentication object inside the - SecurityContextHolder. The only critical requirement is that - the SecurityContextHolder contains an - Authentication which represents a principal before - the AbstractSecurityInterceptor (which we'll see more about - later) needs to authorize a user operation. - You can (and many users do) write their own filters or MVC controllers to provide - interoperability with authentication systems that are not based on Spring Security. - For example, you might be using Container-Managed Authentication which makes the - current user available from a ThreadLocal or JNDI location. Or you might work for a - company that has a legacy proprietary authentication system, which is a corporate - "standard" over which you have little control. In situations like this it's quite - easy to get Spring Security to work, and still provide authorization capabilities. - All you need to do is write a filter (or equivalent) that reads the third-party user - information from a location, build a Spring Security-specific - Authentication object, and put it into the - SecurityContextHolder. In this case you also need to think - about things which are normally taken care of automatically by the built-in authentication - infrastructure. For example, you might need to pre-emptively create an HTTP session to - cache the context between requests, - before you write the response to the clientIt isn't possible to create a session once the - response has been committed.. - - If you're wondering how the AuthenticationManager - is implemented in a real world example, we'll look at that in the core services - chapter. -
-
-
- Authentication in a Web Application - Now let's explore the situation where you are using Spring Security in a web - application (without web.xml security enabled). How is a user - authenticated and the security context established? - Consider a typical web application's authentication process: - - - You visit the home page, and click on a link. - - - A request goes to the server, and the server decides that you've asked for a - protected resource. - - - As you're not presently authenticated, the server sends back a response - indicating that you must authenticate. The response will either be an HTTP - response code, or a redirect to a particular web page. - - - Depending on the authentication mechanism, your browser will either redirect - to the specific web page so that you can fill out the form, or the browser will - somehow retrieve your identity (via a BASIC authentication dialogue box, a - cookie, a X.509 certificate etc.). - - - The browser will send back a response to the server. This will either be an - HTTP POST containing the contents of the form that you filled out, or an HTTP - header containing your authentication details. - - - Next the server will decide whether or not the presented credentials are - valid. If they're valid, the next step will happen. If they're invalid, usually - your browser will be asked to try again (so you return to step two - above). - - - The original request that you made to cause the authentication process will be - retried. Hopefully you've authenticated with sufficient granted authorities to - access the protected resource. If you have sufficient access, the request will - be successful. Otherwise, you'll receive back an HTTP error code 403, which - means "forbidden". - - - Spring Security has distinct classes responsible for most of the steps described - above. The main participants (in the order that they are used) are the - ExceptionTranslationFilter, an - AuthenticationEntryPoint and an authentication - mechanism, which is responsible for calling the - AuthenticationManager which we saw in the previous - section. -
- ExceptionTranslationFilter - ExceptionTranslationFilter is a Spring Security filter that - has responsibility for detecting any Spring Security exceptions that are thrown. - Such exceptions will generally be thrown by an - AbstractSecurityInterceptor, which is the main provider of - authorization services. We will discuss - AbstractSecurityInterceptor in the next section, but for now - we just need to know that it produces Java exceptions and knows nothing about HTTP - or how to go about authenticating a principal. Instead the - ExceptionTranslationFilter offers this service, with specific - responsibility for either returning error code 403 (if the principal has been - authenticated and therefore simply lacks sufficient access - as per step seven - above), or launching an AuthenticationEntryPoint (if - the principal has not been authenticated and therefore we need to go commence step - three). -
-
- AuthenticationEntryPoint - The AuthenticationEntryPoint is responsible for - step three in the above list. As you can imagine, each web application will have a - default authentication strategy (well, this can be configured like nearly everything - else in Spring Security, but let's keep it simple for now). Each major - authentication system will have its own - AuthenticationEntryPoint implementation, which - typically performs one of the actions described in step 3. -
-
- Authentication Mechanism - Once your browser submits your authentication credentials (either as an HTTP form - post or HTTP header) there needs to be something on the server that - collects these authentication details. By now we're at step six in - the above list. In Spring Security we have a special name for the function of - collecting authentication details from a user agent (usually a web browser), - referring to it as the authentication mechanism. Examples are - form-base login and Basic authentication. Once the authentication details have been - collected from the user agent, an Authentication - request object is built and then presented to the - AuthenticationManager. - After the authentication mechanism receives back the fully-populated - Authentication object, it will deem the request - valid, put the Authentication into the - SecurityContextHolder, and cause the original request to be - retried (step seven above). If, on the other hand, the - AuthenticationManager rejected the request, the - authentication mechanism will ask the user agent to retry (step two above). -
-
- Storing the <interfacename>SecurityContext</interfacename> between - requests - Depending on the type of application, there may need to be a strategy in place to - store the security context between user operations. In a typical web application, a - user logs in once and is subsequently identified by their session Id. The server - caches the principal information for the duration session. In Spring Security, the - responsibility for storing the SecurityContext - between requests falls to the - SecurityContextPersistenceFilter, which by default stores the - context as an HttpSession attribute between HTTP requests. It - restores the context to the SecurityContextHolder for each - request and, crucially, clears the SecurityContextHolder when - the request completes. You shouldn't interact directly with the - HttpSession for security purposes. There is simply no - justification for doing so - always use the - SecurityContextHolder instead. - Many other types of application (for example, a stateless RESTful web service) do - not use HTTP sessions and will re-authenticate on every request. However, it is - still important that the SecurityContextPersistenceFilter is - included in the chain to make sure that the - SecurityContextHolder is cleared after each request. - - In an application which receives concurrent requests in a single session, the - same SecurityContext instance will be shared - between threads. Even though a ThreadLocal is being used, - it is the same instance that is retrieved from the - HttpSession for each thread. This has - implications if you wish to temporarily change the context under which a thread - is running. If you just use SecurityContextHolder.getContext(), and - call setAuthentication(anAuthentication) on the returned context - object, then the Authentication object will - change in all concurrent threads which share the same - SecurityContext instance. You can customize the - behaviour of SecurityContextPersistenceFilter to create a - completely new SecurityContext for each request, - preventing changes in one thread from affecting another. Alternatively you can - create a new instance just at the point where you temporarily change the - context. The method SecurityContextHolder.createEmptyContext() - always returns a new context instance. - -
-
-
- Access-Control (Authorization) in Spring Security - The main interface responsible for making access-control decisions in Spring Security - is the AccessDecisionManager. It has a - decide method which takes an - Authentication object representing the principal - requesting access, a secure object (see below) and a list of security - metadata attributes which apply for the object (such as a list of roles which are - required for access to be granted). -
- Security and AOP Advice - If you're familiar with AOP, you'd be aware there are different types of advice - available: before, after, throws and around. An around advice is very useful, - because an advisor can elect whether or not to proceed with a method invocation, - whether or not to modify the response, and whether or not to throw an exception. - Spring Security provides an around advice for method invocations as well as web - requests. We achieve an around advice for method invocations using Spring's standard - AOP support and we achieve an around advice for web requests using a standard - Filter. - For those not familiar with AOP, the key point to understand is that Spring - Security can help you protect method invocations as well as web requests. Most - people are interested in securing method invocations on their services layer. This - is because the services layer is where most business logic resides in - current-generation J2EE applications. If you just need to secure method invocations - in the services layer, Spring's standard AOP will be adequate. If you need to secure - domain objects directly, you will likely find that AspectJ is worth - considering. - You can elect to perform method authorization using AspectJ or Spring AOP, or you - can elect to perform web request authorization using filters. You can use zero, one, - two or three of these approaches together. The mainstream usage pattern is to - perform some web request authorization, coupled with some Spring AOP method - invocation authorization on the services layer. -
-
- Secure Objects and the <classname>AbstractSecurityInterceptor</classname> - So what is a secure object anyway? Spring - Security uses the term to refer to any object that can have security (such as an - authorization decision) applied to it. The most common examples are method - invocations and web requests. - Each supported secure object type has its own interceptor class, which is a - subclass of AbstractSecurityInterceptor. Importantly, by the - time the AbstractSecurityInterceptor is called, the - SecurityContextHolder will contain a valid - Authentication if the principal has been - authenticated. - AbstractSecurityInterceptor provides a consistent workflow - for handling secure object requests, typically: - - Look up the configuration attributes associated with the - present request - - - Submitting the secure object, current - Authentication and configuration attributes - to the AccessDecisionManager for an - authorization decision - - - Optionally change the Authentication under - which the invocation takes place - - - Allow the secure object invocation to proceed (assuming access was - granted) - - - Call the AfterInvocationManager if - configured, once the invocation has returned. If the invocation raised an - exception, the AfterInvocationManager - will not be invoked. - - -
- What are Configuration Attributes? - A configuration attribute can be thought of as a String that - has special meaning to the classes used by - AbstractSecurityInterceptor. They are represented by the - interface ConfigAttribute within the framework. - They may be simple role names or have more complex meaning, depending on the how - sophisticated the AccessDecisionManager - implementation is. The AbstractSecurityInterceptor is - configured with a SecurityMetadataSource which it - uses to look up the attributes for a secure object. Usually this configuration - will be hidden from the user. Configuration attributes will be entered as - annotations on secured methods or as access attributes on secured URLs. For - example, when we saw something like <intercept-url - pattern='/secure/**' access='ROLE_A,ROLE_B'/> in the namespace - introduction, this is saying that the configuration attributes - ROLE_A and ROLE_B apply to web requests - matching the given pattern. In practice, with the default - AccessDecisionManager configuration, this means - that anyone who has a GrantedAuthority matching - either of these two attributes will be allowed access. Strictly speaking though, - they are just attributes and the interpretation is dependent on the - AccessDecisionManager implementation. The use of - the prefix ROLE_ is a marker to indicate that these - attributes are roles and should be consumed by Spring Security's - RoleVoter. This is only relevant when a voter-based - AccessDecisionManager is in use. We'll see how - the AccessDecisionManager is implemented in the - authorization chapter. -
-
- RunAsManager - Assuming AccessDecisionManager decides to allow - the request, the AbstractSecurityInterceptor will - normally just proceed with the request. Having said that, on rare occasions - users may want to replace the Authentication - inside the SecurityContext with a different - Authentication, which is handled by the - AccessDecisionManager calling a - RunAsManager. This might be useful in reasonably unusual - situations, such as if a services layer method needs to call a remote system and - present a different identity. Because Spring Security automatically propagates - security identity from one server to another (assuming you're using a - properly-configured RMI or HttpInvoker remoting protocol client), this may be - useful. -
-
- AfterInvocationManager - Following the secure object invocation proceeding and then returning - which may mean a - method invocation completing or a filter chain proceeding - the - AbstractSecurityInterceptor gets one final chance to - handle the invocation. At this stage the - AbstractSecurityInterceptor is interested in possibly - modifying the return object. We might want this to happen because an - authorization decision couldn't be made on the way in to a secure - object invocation. Being highly pluggable, - AbstractSecurityInterceptor will pass control to an - AfterInvocationManager to actually modify the object if - needed. This class can even entirely replace the object, or throw an exception, - or not change it in any way as it chooses. The after-invocation checks will only - be executed if the invocation is successful. If an exception occurs, the additional - checks will be skipped. - - AbstractSecurityInterceptor and its related objects are - shown in .
- Security interceptors and the <quote>secure object</quote> model - - - - - -
-
-
- Extending the Secure Object Model - Only developers contemplating an entirely new way of intercepting and - authorizing requests would need to use secure objects directly. For example, it - would be possible to build a new secure object to secure calls to a messaging - system. Anything that requires security and also provides a way of intercepting - a call (like the AOP around advice semantics) is capable of being made into a - secure object. Having said that, most Spring applications will simply use the - three currently supported secure object types (AOP Alliance - MethodInvocation, AspectJ - JoinPoint and web request - FilterInvocation) with complete transparency. -
-
-
-
- Localization - Spring Security supports localization of exception messages that end users are likely - to see. If your application is designed for English-speaking users, you don't need to do - anything as by default all Security Security messages are in English. If you need to - support other locales, everything you need to know is contained in this section. - All exception messages can be localized, including messages related to authentication - failures and access being denied (authorization failures). Exceptions and logging - messages that are focused on developers or system deployers (including incorrect - attributes, interface contract violations, using incorrect constructors, startup time - validation, debug-level logging) are not localized and instead are hard-coded in English - within Spring Security's code. - Shipping in the spring-security-core-xx.jar you will find an - org.springframework.security package that in turn contains a - messages.properties file, as well as localized versions for some - common languages. This should be referred to by your - ApplicationContext, as Spring Security classes implement Spring's - MessageSourceAware interface and expect the message resolver to be - dependency injected at application context startup time. Usually all you need to do is - register a bean inside your application context to refer to the messages. An example is - shown below: - - - - -]]> - - The messages.properties is named in accordance with standard - resource bundles and represents the default language supported by Spring Security - messages. This default file is in English. - If you wish to customize the messages.properties file, or support - other languages, you should copy the file, rename it accordingly, and register it inside - the above bean definition. There are not a large number of message keys inside this - file, so localization should not be considered a major initiative. If you do perform - localization of this file, please consider sharing your work with the community by - logging a JIRA task and attaching your appropriately-named localized version of - messages.properties. - Spring Security relies on Spring's localization support in order to actually lookup - the appropriate message. In order for this to work, you have to make sure that the - locale from the incoming request is stored in Spring's - org.springframework.context.i18n.LocaleContextHolder. Spring - MVC's DispatcherServlet does this for your application - automatically, but since Spring Security's filters are invoked before this, the - LocaleContextHolder needs to be set up to contain the correct - Locale before the filters are called. You can either do this in a - filter yourself (which must come before the Spring Security filters in - web.xml) or you can use Spring's - RequestContextFilter. Please refer to the Spring Framework - documentation for further details on using localization with Spring. - The contacts sample application is set up to use localized messages. - -
-
diff --git a/docs/manual/src/docbook/x509-auth-provider.xml b/docs/manual/src/docbook/x509-auth-provider.xml deleted file mode 100644 index ec931d5abb..0000000000 --- a/docs/manual/src/docbook/x509-auth-provider.xml +++ /dev/null @@ -1,100 +0,0 @@ - - - X.509 Authentication - - -
- - Overview - - - The most common use of X.509 certificate authentication is in verifying the identity - of a server when using SSL, most commonly when using HTTPS from a browser. The browser - will automatically check that the certificate presented by a server has been issued (ie - digitally signed) by one of a list of trusted certificate authorities which it - maintains. - You can also use SSL with mutual authentication; the server will then - request a valid certificate from the client as part of the SSL handshake. The server - will authenticate the client by checking that its certificate is signed by an acceptable - authority. If a valid certificate has been provided, it can be obtained through the - servlet API in an application. Spring Security X.509 module extracts the certificate - using a filter. It maps the certificate to an application user and loads that user's set - of granted authorities for use with the standard Spring Security infrastructure. - You should be familiar with using certificates and setting up client authentication - for your servlet container before attempting to use it with Spring Security. Most of the - work is in creating and installing suitable certificates and keys. For example, if - you're using Tomcat then read the instructions here http://tomcat.apache.org/tomcat-6.0-doc/ssl-howto.html. It's important that you - get this working before trying it out with Spring Security -
-
- - Adding X.509 Authentication to Your Web Application - - - Enabling X.509 client authentication is very straightforward. Just add the - <x509/> element to your http security namespace configuration. - - ... - ; - ... - - ]]> - The element has two optional attributes: - - subject-principal-regex. The regular expression used to - extract a username from the certificate's subject name. The default value is - shown above. This is the username which will be passed to the - UserDetailsService to load the authorities for - the user. - - - user-service-ref. This is the bean Id of the - UserDetailsService to be used with X.509. It - isn't needed if there is only one defined in your application context. - - The subject-principal-regex should contain a single - group. For example the default expression "CN=(.*?)," matches the common name field. So - if the subject name in the certificate is "CN=Jimi Hendrix, OU=...", this will give a - user name of "Jimi Hendrix". The matches are case insensitive. So "emailAddress=(.?)," - will match "EMAILADDRESS=jimi@hendrix.org,CN=..." giving a user name "jimi@hendrix.org". - If the client presents a certificate and a valid username is successfully extracted, - then there should be a valid Authentication object in the - security context. If no certificate is found, or no corresponding user could be found - then the security context will remain empty. This means that you can easily use X.509 - authentication with other options such as a form-based login. -
-
- - Setting up SSL in Tomcat - - - There are some pre-generated certificates in the - samples/certificate directory in the Spring Security project. You - can use these to enable SSL for testing if you don't want to generate your own. The file - server.jks contains the server certificate, private key and the - issuing certificate authority certificate. There are also some client certificate files - for the users from the sample applications. You can install these in your browser to - enable SSL client authentication. - To run tomcat with SSL support, drop the server.jks file into - the tomcat conf directory and add the following connector to the - server.xml file - - ]]> - clientAuth can also be set to want if you - still want SSL connections to succeed even if the client doesn't provide a certificate. - Clients which don't present a certificate won't be able to access any objects secured by - Spring Security unless you use a non-X.509 authentication mechanism, such as form - authentication. -
-
diff --git a/docs/manual/src/resources/css/highlight.css b/docs/manual/src/resources/css/highlight.css deleted file mode 100644 index ffefef72de..0000000000 --- a/docs/manual/src/resources/css/highlight.css +++ /dev/null @@ -1,35 +0,0 @@ -/* - code highlight CSS resemblign the Eclipse IDE default color schema - @author Costin Leau -*/ - -.hl-keyword { - color: #7F0055; - font-weight: bold; -} - -.hl-comment { - color: #3F5F5F; - font-style: italic; -} - -.hl-multiline-comment { - color: #3F5FBF; - font-style: italic; -} - -.hl-tag { - color: #3F7F7F; -} - -.hl-attribute { - color: #7F007F; -} - -.hl-value { - color: #2A00FF; -} - -.hl-string { - color: #2A00FF; -} \ No newline at end of file diff --git a/docs/manual/src/resources/css/manual.css b/docs/manual/src/resources/css/manual.css deleted file mode 100644 index 524d462211..0000000000 --- a/docs/manual/src/resources/css/manual.css +++ /dev/null @@ -1,69 +0,0 @@ -@IMPORT url("highlight.css"); - -html { - padding: 0pt; - margin: 0pt; -} - -body { - margin-left: 10%; - margin-right: 10%; - font-family: Arial, Sans-serif; -} - -div { - margin: 0pt; -} - -p { - text-align: justify; -} - -hr { - border: 1px solid gray; - background: gray; -} - -h1,h2,h3,h4 { - color: #234623; - font-family: Arial, Sans-serif; -} - -pre { - line-height: 1.0; - color: black; -} - -pre.programlisting { - font-size: 10pt; - padding: 7pt 3pt; - border: 1pt solid black; - background: #eeeeee; - clear: both; -} - -div.table { - margin: 1em; - padding: 0.5em; - text-align: center; -} - -div.table table { - display: table; - width: 100%; -} - -div.table td { - padding-left: 7px; - padding-right: 7px; -} - -.sidebar { - float: right; - margin: 10px 0 10px 30px; - padding: 10px 20px 20px 20px; - width: 33%; - border: 1px solid black; - background-color: #F4F4F4; - font-size: 14px; -} diff --git a/docs/manual/src/xsl/html-custom.xsl b/docs/manual/src/xsl/html-custom.xsl deleted file mode 100644 index 5c11bc7931..0000000000 --- a/docs/manual/src/xsl/html-custom.xsl +++ /dev/null @@ -1,145 +0,0 @@ - - - - - - - - - - '5' - '1' - - - 1 - - - 1 - - - 1 - 0 - 1 - - - - images/ - .png - - 120 - images/callouts/ - .png - - - css/manual.css - text/css - book toc,title - - text-align: left - - - - - - - - - - - - - - 3 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Begin Google Analytics code - - - End Google Analytics code - - - - - Begin LoopFuse code - - - End LoopFuse code - - - \ No newline at end of file diff --git a/docs/manual/src/xsl/html-single-custom.xsl b/docs/manual/src/xsl/html-single-custom.xsl deleted file mode 100644 index e979e7f146..0000000000 --- a/docs/manual/src/xsl/html-single-custom.xsl +++ /dev/null @@ -1,142 +0,0 @@ - - - - - - - - - - - 1 - - - 1 - - - 1 - 0 - 1 - - - - images/ - .png - - 120 - images/callouts/ - .png - - - css/manual.css - text/css - book toc,title - - text-align: left - - - - - - - - - - - - - - 2 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Begin Google Analytics code - - -End Google Analytics code - - - - -Begin LoopFuse code - - -End LoopFuse code - - - \ No newline at end of file diff --git a/docs/manual/src/xsl/pdf-custom.xsl b/docs/manual/src/xsl/pdf-custom.xsl deleted file mode 100644 index 08882ffc06..0000000000 --- a/docs/manual/src/xsl/pdf-custom.xsl +++ /dev/null @@ -1,503 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -5em - -5em - - - - - - book toc,title - - - - - - - - - - - - - - - - - please define productname in your docbook file! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1 - 0 - 1 - 1 - - - - - 0 - 0 - 0 - - - - false - - - 11 - 8 - - - 1.4 - - - - left - bold - - - pt - - - - - - - - - - - - - - - - 0.8em - 0.8em - 0.8em - - - pt - - 0.1em - 0.1em - 0.1em - - - 0.6em - 0.6em - 0.6em - - - pt - - 0.1em - 0.1em - 0.1em - - - 0.4em - 0.4em - 0.4em - - - pt - - 0.1em - 0.1em - 0.1em - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 4pt - 4pt - 4pt - 4pt - - - - 0.1pt - 0.1pt - - - - - - - - - - - - - - - - - - pt - - - - - 1em - 1em - 1em - 0.1em - 0.1em - 0.1em - - #444444 - solid - 0.1pt - 0.5em - 0.5em - 0.5em - 0.5em - 0.5em - 0.5em - - - - 1 - - #F0F0F0 - - - - 0.1em - 0.1em - 0.1em - 0.1em - 0.1em - 0.1em - - - - 0.5em - 0.5em - 0.5em - 0.1em - 0.1em - 0.1em - always - - - - - - normal - italic - - - pt - - false - 0.1em - 0.1em - 0.1em - - - - - - - - - - - figure after - example after - equation before - table before - procedure before - - - - 1 - - 0pt - - - 3 - - - - - - - - - - - - - - - - - -