I want to secure my services with spring security and Json Web Token(JWT) and also store logged users in redis with spring session.So when user sends login request i authenticate user and i send generated token back like below:public ResponseEntity<?> createAuthenticationToken(@RequestBody JwtAuthenticationRequest authenticationRequest, Device device) throws AuthenticationException { // Perform the security final Authentication authentication = authenticationManager.authenticate( new UsernamePasswordAuthenticationToken( authenticationRequest.getUsername(), authenticationRequest.getPassword() ) ); SecurityContextHolder.getContext().setAuthentication(authentication); final UserDetails userDetails = userDetailsService.loadUserByUsername(authenticationRequest.getUsername()); final String token = jwtTokenUtil.generateToken(userDetails, device); // Return the token return ResponseEntity.ok(new JwtAuthenticationResponse(token));}我也将该用户添加到会话(支持Redis会话)中:And also i add that user to session(backed Redis session):HttpSession session = request.getSession(false); if (session != null) { session.setMaxInactiveInterval(30 * 600); JwtUser user = (JwtUser) authentication.getPrincipal(); session.setAttribute("user", user); }我检查redis之后,我看到用户会话已经设置为redis.但是当我收到来自用户的下一次尝试时,它变为 anonymousUser ,理想情况下不应该这样做.原因背后的原因是传入的JSESSIONID是无效.After i check redis , i see user session already set to redis.But when i receive next attempt from user it became anonymousUser , ideally it shouldn't.Reason behind this problem is incoming JSESSIONID is invalid somehow. Authentication auth = SecurityContextHolder.getContext().getAuthentication();我看到调试屏幕委托返回匿名用户.I see debug screen Principal returns anonymousUser.我也尝试如下:@RequestMapping(value = "/username", method = RequestMethod.GET)@ResponseBodypublic String currentUserNameSimple(HttpServletRequest request) { Principal principal = request.getUserPrincipal(); return principal.getName();}但是principal为空.But principal is null.我的redis配置:@Configuration@EnableRedisHttpSession public class RedisConfig implements BeanClassLoaderAware {private ClassLoader loader;@Bean(name = { "defaultRedisSerializer", "springSessionDefaultRedisSerializer" })public RedisSerializer<Object> springSessionDefaultRedisSerializer() { return new GenericJackson2JsonRedisSerializer(objectMapper());}@Beanpublic HttpSessionStrategy httpSessionStrategy() { return new HeaderHttpSessionStrategy(); }@BeanJedisConnectionFactory jedisConnectionFactory() { JedisConnectionFactory jedisConFactory = new JedisConnectionFactory(); jedisConFactory.setHostName("localhost"); jedisConFactory.setPort(6379); return jedisConFactory;}ObjectMapper objectMapper() { ObjectMapper mapper = new ObjectMapper(); mapper.registerModules(SecurityJackson2Modules.getModules(this.loader)); return mapper;}public void setBeanClassLoader(ClassLoader classLoader) { this.loader = classLoader;}} Maven依赖项:<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-tomcat</artifactId> <scope>provided</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-mail</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-configuration-processor</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> <version>1.4.3.RELEASE</version> </dependency> <!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-core --> <!-- Password Validation --> <dependency> <groupId>org.passay</groupId> <artifactId>passay</artifactId> <version>${passay.version}</version> </dependency> <dependency> <groupId>org.springframework.mobile</groupId> <artifactId>spring-mobile-device</artifactId> <version>1.1.4.RELEASE</version> </dependency> <!--JWT --> <dependency> <groupId>io.jsonwebtoken</groupId> <artifactId>jjwt</artifactId> <version>0.7.0</version> </dependency> <dependency> <groupId>az.com.cybernet.utilities</groupId> <artifactId>utilities</artifactId> <version>0.0.1</version> <scope>compile</scope> </dependency> <dependency> <groupId>az.com.cybernet.beans</groupId> <artifactId>disieibeans</artifactId> <version>0.0.1</version> <scope>compile</scope> </dependency> <!-- DB dependencies --> <dependency> <groupId>org.postgresql</groupId> <artifactId>postgresql</artifactId> <version>9.4-1200-jdbc41</version> </dependency> <dependency> <groupId>javax.el</groupId> <artifactId>el-api</artifactId> <version>2.2</version> </dependency> <dependency> <groupId>net.logstash.logback</groupId> <artifactId>logstash-logback-encoder</artifactId> <version>4.8</version> </dependency> <!-- REDIS --> <dependency> <groupId>org.springframework.session</groupId> <artifactId>spring-session-data-redis</artifactId> <version>2.0.0.BUILD-SNAPSHOT</version> <type>pom</type> </dependency> <dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> <version>2.5.1</version> </dependency> <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-core</artifactId> <version>4.2.0.RELEASE</version> </dependency></dependencies>没有Redis,一切都很好,但是使用Redis,我无法获得当前经过身份验证的用户的委托人Without Redis everything is works good, But with redis i cannot get currently authenticated user's principal推荐答案我只是将jedis客户端更改为生菜客户端,如下所示,它解决了问题:i just changed jedis client to lettuce client like below and it solved problem: <dependency> <groupId>biz.paluch.redis</groupId> <artifactId>lettuce</artifactId> <version>3.5.0.Final</version> </dependency>在春季安全性Principal对象为空之前,因为Jedis客户端未创建名为"JSESSIONID"的cookie.Before spring security Principal object was null because cookie named "JSESSIONID" hadn't created by Jedis client.@EnableRedisHttpSessionpublic class RedisConfig {@Beanpublic LettuceConnectionFactory connectionFactory() { return new LettuceConnectionFactory();}@Beanpublic CookieSerializer cookieSerializer() { DefaultCookieSerializer serializer = new DefaultCookieSerializer(); serializer.setCookieName("JSESSIONID"); // <1> serializer.setCookiePath("/"); // <2> serializer.setDomainNamePattern("^.+?\\.(\\w+\\.[a-z]+)$"); // <3> return serializer;}} 这篇关于如何在Spring Boot应用程序中使用Spring Security和Redis获取当前已认证的用户Principal的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!
09-22 11:29