How can i get currently authenticated user Principal with spring security and Redis in spring boot application

点点圈 提交于 2019-12-11 05:47:15

问题


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));
}

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);

    }

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.

Also i try as follows:

@RequestMapping(value = "/username", method = RequestMethod.GET)
@ResponseBody
public String currentUserNameSimple(HttpServletRequest request) {
    Principal principal = request.getUserPrincipal();
    return principal.getName();
}

But principal is null.

My redis config:

@Configuration
@EnableRedisHttpSession 
public class RedisConfig implements BeanClassLoaderAware {

private ClassLoader loader;


@Bean(name = { "defaultRedisSerializer", "springSessionDefaultRedisSerializer" })
public RedisSerializer<Object> springSessionDefaultRedisSerializer() {
    return new GenericJackson2JsonRedisSerializer(objectMapper());

}

@Bean
public HttpSessionStrategy httpSessionStrategy() {
        return new HeaderHttpSessionStrategy(); 
}

@Bean
JedisConnectionFactory 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:

<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>

Without Redis everything is works good, But with redis i cannot get currently authenticated user's principal


回答1:


i solved my problem .I change jedis client with lettuce client as follows:

     <dependency>
        <groupId>biz.paluch.redis</groupId>
        <artifactId>lettuce</artifactId>
        <version>3.5.0.Final</version>
    </dependency>

My Principal was null because cookie named "JSESSIONID" hadn't created with Jedis client, so it solved with lettuce 3.5.0.Final version.

@EnableRedisHttpSession
public class RedisConfig {
@Bean
public LettuceConnectionFactory connectionFactory() {
    return new LettuceConnectionFactory();
}

@Bean
public CookieSerializer cookieSerializer() {
    DefaultCookieSerializer serializer = new DefaultCookieSerializer();
    serializer.setCookieName("JSESSIONID"); // <1>
    serializer.setCookiePath("/"); // <2>
    serializer.setDomainNamePattern("^.+?\\.(\\w+\\.[a-z]+)$"); // <3>
    return serializer;
}
}



回答2:


Similar Question Asked Here.

Make a call to redisOperationsSessionRepository with auth-key/sessionId.

Hope it helps:)



来源:https://stackoverflow.com/questions/41777267/how-can-i-get-currently-authenticated-user-principal-with-spring-security-and-re

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!