我有一个使用 Redis HttpSession 存储的 Java 8 spring boot 项目。但是,我想将其更改为使用 Mongo HttpSession 存储。我改变了我的深度:
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-data-redis</artifactId>
<version>1.3.1.RELEASE</version>
</dependency>
到:
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-data-mongo</artifactId>
<version>1.3.1.RELEASE</version>
</dependency>
并且我将相应的配置注解从@EnableRedisHttpSession 更改为@EnableMongoHttpSession。
但是,当我运行以下命令时,服务会输出如下所示的堆栈跟踪。
$ curl -i --cookie-jar cookie.jar -d "username=jkaldon&password=abc123" --header "Content-Type: application/x-www-form-urlencoded" --header "Host: authentication.services.mycompany.com" -X POST http://localhost:8080/api/v1/login
HTTP/1.1 200
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Expires: 0
X-Frame-Options: DENY
Set-Cookie: XSRF-TOKEN=b3b28861-8ce8-4629-a54c-d6d73039a3ee; Domain=mycompany.com; Path=/; HttpOnly
Set-Cookie: SESSION=3a2846ee-4d7b-4e12-970a-81617f6b8b18; Domain=mycompany.com; Path=/; HttpOnly
Content-Type: application/json;charset=ISO-8859-1
Content-Length: 312
Date: Wed, 25 Oct 2017 18:36:08 GMT
{"sessionId":"3a2846ee-4d7b-4e12-970a-81617f6b8b18","xsrfToken":"b3b28861-8ce8-4629-a54c-d6d73039a3ee","currentUser":{"userId":"slkdjfois","firstName":"Joshua","lastName":"Kaldon","avatarUrl":"https://s3.amazonaws.com/uifaces/faces/twitter/mohanrohith/128.jpg"},"brandConfiguration":{"navBarTitle":"Sale Winds"}}
$ curl -v -b cookie.jar --cookie-jar cookie.jar --header "Host: authentication.mycompany.com" --header "X-XSRF-TOKEN: b3b28861-8ce8-4629-a54c-d6d73039a3ee" --header "Accept: application/json" -X POST http://localhost:8080/api/v1/validateSession
* Trying ::1...
* TCP_NODELAY set
* Connected to localhost (::1) port 8080 (#0)
> POST /api/v1/validateSession HTTP/1.1
> Host: authentication.mycompany.com
> User-Agent: curl/7.54.0
> Cookie: SESSION=3a2846ee-4d7b-4e12-970a-81617f6b8b18; XSRF-TOKEN=b3b28861-8ce8-4629-a54c-d6d73039a3ee
> X-XSRF-TOKEN: b3b28861-8ce8-4629-a54c-d6d73039a3ee
> Accept: application/json
>
< HTTP/1.1 500
< X-Content-Type-Options: nosniff
< X-XSS-Protection: 1; mode=block
< Cache-Control: no-cache, no-store, max-age=0, must-revalidate
< Pragma: no-cache
< Expires: 0
< X-Frame-Options: DENY
< Content-Type: application/json;charset=UTF-8
< Transfer-Encoding: chunked
< Date: Wed, 25 Oct 2017 18:39:29 GMT
< Connection: close
<
* Closing connection 0
{"timestamp":1508956769703,"status":500,"error":"Internal Server Error","exception":"org.springframework.expression.spel.SpelEvaluationException","message":"EL1008E: Property or field 'authentication' cannot be found on object of type 'java.util.LinkedHashMap' - maybe not public?","path":"/api/v1/validateSession"}
堆栈跟踪如下:
13:12:38.553 WARN o.s.s.w.c.HttpSessionSecurityContextRepository - SPRING_SECURITY_CONTEXT did not contain a SecurityContext but contained: '{authentication={authorities=[{role=ROLE_USER}], details={remoteAddress=127.0.0.1, sessionId=null}, authenticated=true, principal={password=null, username=jkaldon, authorities=[{role=ROLE_USER}], accountNonExpired=true, accountNonLocked=true, credentialsNonExpired=true, enabled=true}, credentials=null}}'; are you improperly modifying the HttpSession directly (you should always use SecurityContextHolder) or using the HttpSession attribute reserved for this class?
13:12:38.565 ERROR o.a.c.c.C.[.[.[.[dispatcherServlet] - Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception
org.springframework.expression.spel.SpelEvaluationException: EL1008E: Property or field 'authentication' cannot be found on object of type 'java.util.LinkedHashMap' - maybe not public?
at org.springframework.expression.spel.ast.PropertyOrFieldReference.readProperty(PropertyOrFieldReference.java:226)
at org.springframework.expression.spel.ast.PropertyOrFieldReference.getValueInternal(PropertyOrFieldReference.java:94)
at org.springframework.expression.spel.ast.PropertyOrFieldReference.getValueInternal(PropertyOrFieldReference.java:81)
at org.springframework.expression.spel.ast.CompoundExpression.getValueRef(CompoundExpression.java:51)
at org.springframework.expression.spel.ast.CompoundExpression.getValueInternal(CompoundExpression.java:87)
at org.springframework.expression.spel.ast.SpelNodeImpl.getTypedValue(SpelNodeImpl.java:132)
at org.springframework.expression.spel.standard.SpelExpression.getValue(SpelExpression.java:233)
at org.springframework.session.data.mongo.AuthenticationParser.extractName(AuthenticationParser.java:41)
at org.springframework.session.data.mongo.AbstractMongoSessionConverter.extractPrincipal(AbstractMongoSessionConverter.java:85)
at org.springframework.session.data.mongo.JacksonMongoSessionConverter.convert(JacksonMongoSessionConverter.java:88)
at org.springframework.session.data.mongo.AbstractMongoSessionConverter.convert(AbstractMongoSessionConverter.java:110)
at org.springframework.session.data.mongo.MongoOperationsSessionRepository.convertToDBObject(MongoOperationsSessionRepository.java:141)
at org.springframework.session.data.mongo.MongoOperationsSessionRepository.save(MongoOperationsSessionRepository.java:77)
at org.springframework.session.data.mongo.MongoOperationsSessionRepository.save(MongoOperationsSessionRepository.java:44)
at org.springframework.session.web.http.SessionRepositoryFilter$SessionRepositoryRequestWrapper.commitSession(SessionRepositoryFilter.java:245)
at org.springframework.session.web.http.SessionRepositoryFilter$SessionRepositoryRequestWrapper.access$100(SessionRepositoryFilter.java:217)
at org.springframework.session.web.http.SessionRepositoryFilter.doFilterInternal(SessionRepositoryFilter.java:170)
at org.springframework.session.web.http.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:80)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:197)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.boot.actuate.autoconfigure.MetricsFilter.doFilterInternal(MetricsFilter.java:106)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:199)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:478)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:81)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:342)
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:803)
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:868)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1459)
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:745)
另外,仅供参考,这是运行第一个命令后在 mongo 中显示的内容:
> db.sessions.find().pretty()
{
"_id" : "3a2846ee-4d7b-4e12-970a-81617f6b8b18",
"created" : NumberLong("1508956567988"),
"accessed" : NumberLong("1508956567988"),
"interval" : 1800,
"expireAt" : NumberLong("1508958367988"),
"attrs" : {
"SPRING_SECURITY_CONTEXT" : {
"authentication" : {
"authorities" : [
{
"role" : "ROLE_USER"
}
],
"details" : {
"remoteAddress" : "0:0:0:0:0:0:0:1",
"sessionId" : null
},
"authenticated" : true,
"principal" : {
"password" : null,
"username" : "jkaldon",
"authorities" : [
{
"role" : "ROLE_USER"
}
],
"accountNonExpired" : true,
"accountNonLocked" : true,
"credentialsNonExpired" : true,
"enabled" : true
},
"credentials" : null
}
}
},
"principal" : "jkaldon"
}
现在请记住,当我使用 Redis 时,所有这些都可以正常工作。
谢谢。