diff --git a/rapidoid-commons/src/main/resources/rapidoid-classes.txt b/rapidoid-commons/src/main/resources/rapidoid-classes.txt index 16c358e498..bd334e70dc 100644 --- a/rapidoid-commons/src/main/resources/rapidoid-classes.txt +++ b/rapidoid-commons/src/main/resources/rapidoid-classes.txt @@ -371,6 +371,7 @@ org.rapidoid.http.impl.RespImpl org.rapidoid.http.impl.ResponseRenderer org.rapidoid.http.impl.RouteImpl org.rapidoid.http.impl.RouteOptions +org.rapidoid.http.impl.TokenStatus org.rapidoid.http.NotFound org.rapidoid.http.processor.AbstractHttpProcessor org.rapidoid.http.processor.HttpProcessor diff --git a/rapidoid-http-fast/src/main/java/org/rapidoid/http/impl/ReqImpl.java b/rapidoid-http-fast/src/main/java/org/rapidoid/http/impl/ReqImpl.java index d226ec353c..d48ee75da1 100644 --- a/rapidoid-http-fast/src/main/java/org/rapidoid/http/impl/ReqImpl.java +++ b/rapidoid-http-fast/src/main/java/org/rapidoid/http/impl/ReqImpl.java @@ -5,6 +5,7 @@ import org.rapidoid.annotation.Since; import org.rapidoid.buffer.Buf; import org.rapidoid.cls.Cls; +import org.rapidoid.commons.Coll; import org.rapidoid.commons.MediaType; import org.rapidoid.commons.Str; import org.rapidoid.http.*; @@ -23,6 +24,7 @@ import java.io.Serializable; import java.util.*; import java.util.Map.Entry; +import java.util.concurrent.atomic.AtomicBoolean; /* * #%L @@ -86,6 +88,10 @@ public class ReqImpl extends RapidoidThing implements Req, Constants, HttpMetada private volatile Map token; + final AtomicBoolean isTokenDirty = new AtomicBoolean(); + + private volatile TokenStatus tokenStatus = TokenStatus.PENDING; + private volatile Map session; private volatile RespImpl response; @@ -419,7 +425,7 @@ public void startRendering(int code, boolean unknownContentLength) { private void startResponse(int code, boolean unknownContentLength) { MediaType contentType = MediaType.HTML_UTF_8; - if (token != null) { + if (isTokenDirty.get()) { HttpUtils.saveTokenBeforeRenderingHeaders(this, token); } @@ -674,24 +680,29 @@ public T session(String name, T defaultValue) { @Override public boolean hasToken() { - return U.notEmpty(token) || cookie(TOKEN, null) != null || data(TOKEN, null) != null; + token(); // try to find and deserialize the token + return tokenStatus != TokenStatus.NONE; } @Override public Map token() { - if (token == null) { + if (tokenStatus == TokenStatus.PENDING) { synchronized (this) { - if (token == null) { - Map cpack = null; + if (tokenStatus == TokenStatus.PENDING) { + + Map tokenData = null; try { - cpack = HttpUtils.initAndDeserializeToken(this); + tokenData = HttpUtils.initAndDeserializeToken(this); + + tokenStatus(tokenData != null ? TokenStatus.LOADED : TokenStatus.NONE); + } catch (Exception e) { - Log.warn("Cookie-pack deserialization error! Maybe the secret was changed?"); - Log.debug("Cookie-pack deserialization error!", e); + Log.debug("Token deserialization error!", e); + tokenStatus(TokenStatus.INVALID); } - token = Collections.synchronizedMap(U.safe(cpack)); + token = Coll.trackChanges(Collections.synchronizedMap(U.safe(tokenData)), isTokenDirty); } } } @@ -712,6 +723,15 @@ public T token(String name, T defaultValue) { return withDefault(value, defaultValue); } + public TokenStatus tokenStatus() { + return tokenStatus; + } + + public Req tokenStatus(TokenStatus tokenStatus) { + this.tokenStatus = tokenStatus; + return this; + } + @Override public String segment() { return segment; diff --git a/rapidoid-http-fast/src/main/java/org/rapidoid/http/impl/RespImpl.java b/rapidoid-http-fast/src/main/java/org/rapidoid/http/impl/RespImpl.java index ab38353497..71ababe3d1 100644 --- a/rapidoid-http-fast/src/main/java/org/rapidoid/http/impl/RespImpl.java +++ b/rapidoid-http-fast/src/main/java/org/rapidoid/http/impl/RespImpl.java @@ -322,12 +322,15 @@ public Req request() { @Override public boolean login(String username, String password) { + LoginProvider loginProvider = Customization.of(req).loginProvider(); U.must(loginProvider != null, "A login provider wasn't set!"); RolesProvider rolesProvider = Customization.of(req).rolesProvider(); U.must(rolesProvider != null, "A roles provider wasn't set!"); + req.isTokenDirty.set(true); + boolean success; try { @@ -356,6 +359,7 @@ public boolean login(String username, String password) { public void logout() { HttpUtils.clearUserData(request()); HttpUtils.setResponseTokenCookie(this, ""); + req.isTokenDirty.set(true); } @Override diff --git a/rapidoid-http-fast/src/main/java/org/rapidoid/http/impl/TokenStatus.java b/rapidoid-http-fast/src/main/java/org/rapidoid/http/impl/TokenStatus.java new file mode 100644 index 0000000000..63bc7640e3 --- /dev/null +++ b/rapidoid-http-fast/src/main/java/org/rapidoid/http/impl/TokenStatus.java @@ -0,0 +1,32 @@ +package org.rapidoid.http.impl; + +/* + * #%L + * rapidoid-http-fast + * %% + * Copyright (C) 2014 - 2016 Nikolche Mihajlovski and contributors + * %% + * 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. + * #L% + */ + +import org.rapidoid.annotation.Authors; +import org.rapidoid.annotation.Since; + +@Authors("Nikolche Mihajlovski") +@Since("5.2.0") +public enum TokenStatus { + + PENDING, NONE, LOADED, INVALID; + +} diff --git a/rapidoid-integration-tests/src/test/resources/test-results/HttpLoginTest/randomUserLogin/granted-abc b/rapidoid-integration-tests/src/test/resources/test-results/HttpLoginTest/randomUserLogin/granted-abc index 4f2ff9bd63..9cc268d3dd 100644 --- a/rapidoid-integration-tests/src/test/resources/test-results/HttpLoginTest/randomUserLogin/granted-abc +++ b/rapidoid-integration-tests/src/test/resources/test-results/HttpLoginTest/randomUserLogin/granted-abc @@ -3,7 +3,6 @@ Connection: keep-alive Server: Rapidoid Date: XXXXX GMT Content-Type: application/json; charset=utf-8 -Set-Cookie: _token=...; path=/; HttpOnly Content-Length: 5 "abc" \ No newline at end of file diff --git a/rapidoid-integration-tests/src/test/resources/test-results/HttpLoginTest/randomUserLogin/granted-chuck b/rapidoid-integration-tests/src/test/resources/test-results/HttpLoginTest/randomUserLogin/granted-chuck index c202a776a0..7e6f7b835c 100644 --- a/rapidoid-integration-tests/src/test/resources/test-results/HttpLoginTest/randomUserLogin/granted-chuck +++ b/rapidoid-integration-tests/src/test/resources/test-results/HttpLoginTest/randomUserLogin/granted-chuck @@ -3,7 +3,6 @@ Connection: keep-alive Server: Rapidoid Date: XXXXX GMT Content-Type: application/json; charset=utf-8 -Set-Cookie: _token=...; path=/; HttpOnly Content-Length: 7 "chuck" \ No newline at end of file diff --git a/rapidoid-integration-tests/src/test/resources/test-results/HttpLoginTest/randomUserLogin/granted-foo b/rapidoid-integration-tests/src/test/resources/test-results/HttpLoginTest/randomUserLogin/granted-foo index 263f9cda71..836b98e22b 100644 --- a/rapidoid-integration-tests/src/test/resources/test-results/HttpLoginTest/randomUserLogin/granted-foo +++ b/rapidoid-integration-tests/src/test/resources/test-results/HttpLoginTest/randomUserLogin/granted-foo @@ -3,7 +3,6 @@ Connection: keep-alive Server: Rapidoid Date: XXXXX GMT Content-Type: application/json; charset=utf-8 -Set-Cookie: _token=...; path=/; HttpOnly Content-Length: 5 "foo" \ No newline at end of file diff --git a/rapidoid-integration-tests/src/test/resources/test-results/HttpLoginTest/randomUserLogin/granted-niko b/rapidoid-integration-tests/src/test/resources/test-results/HttpLoginTest/randomUserLogin/granted-niko index 50a8debf1b..afe0093d11 100644 --- a/rapidoid-integration-tests/src/test/resources/test-results/HttpLoginTest/randomUserLogin/granted-niko +++ b/rapidoid-integration-tests/src/test/resources/test-results/HttpLoginTest/randomUserLogin/granted-niko @@ -3,7 +3,6 @@ Connection: keep-alive Server: Rapidoid Date: XXXXX GMT Content-Type: application/json; charset=utf-8 -Set-Cookie: _token=...; path=/; HttpOnly Content-Length: 6 "niko" \ No newline at end of file diff --git a/rapidoid-integration-tests/src/test/resources/test-results/HttpLoginTest/randomUserLogin/logout b/rapidoid-integration-tests/src/test/resources/test-results/HttpLoginTest/randomUserLogin/logout index 4099647a5c..d58fbe8210 100644 --- a/rapidoid-integration-tests/src/test/resources/test-results/HttpLoginTest/randomUserLogin/logout +++ b/rapidoid-integration-tests/src/test/resources/test-results/HttpLoginTest/randomUserLogin/logout @@ -3,7 +3,6 @@ Connection: keep-alive Server: Rapidoid Date: XXXXX GMT Content-Type: application/json; charset=utf-8 -Set-Cookie: _token=; path=/; HttpOnly Content-Length: 85 {"error":"The user doesn't have the required roles!","code":403,"status":"Forbidden"} \ No newline at end of file