Giter VIP home page Giter VIP logo

spring-security-stateless's Introduction

spring-security-stateless

CircleCI License JitPack

tl;dr

This library provides cookie-based implementations of SecurityContextRepository, CsrfTokenRepository, and RequestCache for Spring Security. This allows you to use Spring Security for authentication in your JVM-based application without using HttpSession, eliminating server-side non-persistent user state and simplifying deployments.

Explanation

HttpSession is standard way to maintain user state in server memory between requests in Java-based web applications. They are easy to use as long as certain precautions are taken, and many frameworks and libraries are based on using HttpSession. If your application takes care of its own authentication (rather than delegating to some access manager reverse proxy), it most likely uses HttpSession to track users' authentication state.

From an operational point of view, using sessions in server memory is problematic since it typically means that each user is must be pegged to the application instance that maintains their session. This is typically implemented using "sticky sessions" or "session persistence" at the load balancer level based on the JSESSIONID cookie.

Performing application deployments without disrupting end users becomes trickier even if techniques such as blue-green deployments are used. An instance can't be stopped until it no longer maintains any user sessions. Solutions exist, such as session replication or persisting user sessions in a database, but these have other drawbacks which means that operations are not necessarily simplified.

This library allows you to use Spring Security for authentication without using HttpSession. Authentication state is kept in an encrypted and signed cookie instead. Specificially, this library provides cookie-based implementations of SecurityContextRepository, CsrfTokenRepository, and RequestCache. These can be used all together or independently.

See the sample Spring Boot application in the src/sampleapp directory for an example of an application using all three implementations and not using HttpSession at all.

This library has been extracted from an application that has been using it in production since January 2016: AusDTO/citizenship-appointment-server

Requirements

Add to your build

Check the Releases tab for the latest version.

Gradle

Add https://jitpack.io as a repository to your Gradle build file (likely build.gradle):

repositories {
    ...
    maven { url 'https://jitpack.io' }
}

Then add the dependency:

dependencies {
    ...
    compile 'com.github.AusDTO:spring-security-stateless:v1.2.3'
}

Maven

Add https://jitpack.io as a repository to your Maven POM file (likely pom.xml):

<repositories>
    <repository>
        <id>jitpack.io</id>
        <url>https://jitpack.io</url>
    </repository>
</repositories>

Then add the dependency:

<dependency>
    <groupId>com.github.AusDTO</groupId>
    <artifactId>spring-security-stateless</artifactId>
    <version>v1.2.3</version>
</dependency>

sbt or Leiningen

See JitPack.io for instructions

How to use

Instructions coming soon. In the meantime, see the example application in the directory src/sampleapp.

Generating a key for encrypting and signing

To generate a key for encrypting and signing use this command on Unix and macOS:

openssl rand 32 | base64

Alternatively you can use the following Java code:

java.security.SecureRandom secureRandom = new java.security.SecureRandom();
byte[] key = new byte[32];
secureRandom.nextBytes(key);
String encodedKey = java.util.Base64.getEncoder().encodeToString(key);
System.out.println(encodedKey);

API documentation

Javadoc

spring-security-stateless's People

Contributors

halvards avatar

Stargazers

deadman avatar  avatar  avatar  avatar  avatar tanghuailong avatar Stefan Fussenegger avatar Anthony avatar Jose Almenarez avatar Dean Qin avatar  avatar

Watchers

 avatar James Cloos avatar Chris Drake avatar

spring-security-stateless's Issues

An attempt was made to write more data to the response headers than there was room available in the buffer

Hello, thanks for your library.

Following your example, I get the following exception. I believe it is the authentication cookie.

org.apache.coyote.http11.HeadersTooLargeException: An attempt was made to write more data to the response headers than there was room available in the buffer. Increase maxHttpHeaderSize on the connector or write less data into the response headers. at org.apache.coyote.http11.Http11OutputBuffer.checkLengthBeforeWrite(Http11OutputBuffer.java:458) ~[tomcat-embed-core-9.0.12.jar:9.0.12] at org.apache.coyote.http11.Http11OutputBuffer.write(Http11OutputBuffer.java:411) ~[tomcat-embed-core-9.0.12.jar:9.0.12] at org.apache.coyote.http11.Http11OutputBuffer.write(Http11OutputBuffer.java:397) ~[tomcat-embed-core-9.0.12.jar:9.0.12] at org.apache.coyote.http11.Http11OutputBuffer.sendHeader(Http11OutputBuffer.java:357) ~[tomcat-embed-core-9.0.12.jar:9.0.12] at org.apache.coyote.http11.Http11Processor.prepareResponse(Http11Processor.java:974) ~[tomcat-embed-core-9.0.12.jar:9.0.12] at org.apache.coyote.AbstractProcessor.action(AbstractProcessor.java:351) ~[tomcat-embed-core-9.0.12.jar:9.0.12] at org.apache.coyote.Response.action(Response.java:211) ~[tomcat-embed-core-9.0.12.jar:9.0.12] at org.apache.coyote.Response.sendHeaders(Response.java:437) ~[tomcat-embed-core-9.0.12.jar:9.0.12] at org.apache.catalina.connector.OutputBuffer.doFlush(OutputBuffer.java:280) ~[tomcat-embed-core-9.0.12.jar:9.0.12] at org.apache.catalina.connector.OutputBuffer.close(OutputBuffer.java:240) ~[tomcat-embed-core-9.0.12.jar:9.0.12] at org.apache.catalina.connector.Response.finishResponse(Response.java:441) ~[tomcat-embed-core-9.0.12.jar:9.0.12] at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:374) ~[tomcat-embed-core-9.0.12.jar:9.0.12] at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:408) ~[tomcat-embed-core-9.0.12.jar:9.0.12] at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66) [tomcat-embed-core-9.0.12.jar:9.0.12] at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:770) [tomcat-embed-core-9.0.12.jar:9.0.12] at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1415) [tomcat-embed-core-9.0.12.jar:9.0.12] at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) [tomcat-embed-core-9.0.12.jar:9.0.12] at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [na:1.8.0_181] at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [na:1.8.0_181] at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-embed-core-9.0.12.jar:9.0.12] at java.lang.Thread.run(Thread.java:748) [na:1.8.0_181]

Cannot deserialize session for anonymous users

Hi,

I have an issue regarding the anonymous users when using this library. When the user is not logged in yet, I get the following exception :

java.lang.RuntimeException: Problem deserializing JSON to Authentication at au.gov.dto.springframework.security.web.context.JsonAuthenticationSerializer.deserialize(JsonAuthenticationSerializer.java:49) ~[spring-security-stateless-v1.2.3.jar:null] at au.gov.dto.springframework.security.web.context.CookieSecurityContextRepository.loadContext(CookieSecurityContextRepository.java:65) ~[spring-security-stateless-v1.2.3.jar:null] at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:86) ~[spring-security-web-4.0.4.RELEASE.jar:4.0.4.RELEASE] at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330) ~[spring-security-web-4.0.4.RELEASE.jar:4.0.4.RELEASE] Caused by: com.fasterxml.jackson.databind.JsonMappingException: No suitable constructor found for type [simple type, class org.springframework.security.authentication.AnonymousAuthenticationToken]: can not instantiate from JSON object (missing default constructor or creator, or perhaps need to add/enable type information?) at [Source: {"@class":"org.springframework.security.authentication.AnonymousAuthenticationToken","details":{"@class":"org.springframework.security.web.authentication.WebAuthenticationDetails","remoteAddress":"0:0:0:0:0:0:0:1","sessionId":null},"authorities":["java.util.ArrayList",[{"@class":"org.springframework.security.core.authority.SimpleGrantedAuthority","role":"ROLE_ANONYMOUS"}]],"authenticated":true,"principal":"anonymousUser","keyHash":-2102752285,"credentials":"","name":"anonymousUser"}; line: 1, column: 85] at com.fasterxml.jackson.databind.JsonMappingException.from(JsonMappingException.java:148) ~[jackson-databind-2.6.7.jar:2.6.7] at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeFromObjectUsingNonDefault(BeanDeserializerBase.java:1106) ~[jackson-databind-2.6.7.jar:2.6.7]

Seems like the AnonymousAuthenticationToken is not properly handled.
If I add .anonymous().disable(), I get another exception :

org.springframework.security.authentication.AuthenticationCredentialsNotFoundException: An Authentication object was not found in the SecurityContext at org.springframework.security.access.intercept.AbstractSecurityInterceptor.credentialsNotFound(AbstractSecurityInterceptor.java:378) at org.springframework.security.access.intercept.AbstractSecurityInterceptor.beforeInvocation(AbstractSecurityInterceptor.java:222) at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:123) at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:90) at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330) at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:114) at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330) at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:122)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.