如何使用 Spring 引导身份验证与 Redis 会话
How to use Spring Boot authentication with Redis session
我正在尝试通过编写一个简单的 REST 应用程序来学习 Spring 启动,该应用程序将让用户登录 (POST /login
) 并显示有关当前用户的信息 (GET /
)。我正在使用 Redis 进行会话。
POST /login
按预期工作:它 returns 主体并在浏览器和 Redis 中设置会话 cookie。
随后 GET /
请求,但是,returns anonymousUser
。我错过了什么?
pom.xml
:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
application.properties
:
spring.session.store-type=redis
server.servlet.session.timeout=3600s
spring.session.redis.flush-mode=on-save
spring.session.redis.namespace=spring:session
spring.redis.host=localhost
spring.redis.port=6379
IndexController.java
:
@Controller
public class IndexController {
private AuthenticationManager authenticationManager;
IndexController(AuthenticationManager authenticationManager) {
this.authenticationManager = authenticationManager;
}
@GetMapping
ResponseEntity index(HttpServletRequest request, HttpSession session) {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
return new ResponseEntity<>(authentication.getPrincipal(), HttpStatus.OK);
}
@PostMapping("/login")
ResponseEntity login(@RequestBody LoginRequest loginRequest) {
String username = loginRequest.getUsername();
String password = loginRequest.getPassword();
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(username, password);
Authentication authentication = this.authenticationManager.authenticate(token);
return new ResponseEntity<>(authentication.getPrincipal(), HttpStatus.OK);
}
}
Config.java
:
@EnableGlobalMethodSecurity(prePostEnabled = true)
@EnableWebSecurity
@EnableRedisHttpSession
@Configuration
public class Config extends WebSecurityConfigurerAdapter {
@Autowired
private CustomUserDetailsService userDetailsService;
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService);
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.ALWAYS)
.and()
.csrf()
.disable()
.authorizeRequests()
.anyRequest()
.permitAll();
}
}
原来我忘了在login
方法中设置authentication
。这是正确的代码。
@PostMapping("/login")
ResponseEntity login(@RequestBody LoginRequest loginRequest) {
String username = loginRequest.getUsername();
String password = loginRequest.getPassword();
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(username, password);
Authentication authentication = this.authenticationManager.authenticate(token);
// vvv THIS vvv
SecurityContextHolder
.getContext()
.setAuthentication(authentication);
return new ResponseEntity<>(authentication.getPrincipal(), HttpStatus.OK);
}
我正在尝试通过编写一个简单的 REST 应用程序来学习 Spring 启动,该应用程序将让用户登录 (POST /login
) 并显示有关当前用户的信息 (GET /
)。我正在使用 Redis 进行会话。
POST /login
按预期工作:它 returns 主体并在浏览器和 Redis 中设置会话 cookie。
随后 GET /
请求,但是,returns anonymousUser
。我错过了什么?
pom.xml
:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
application.properties
:
spring.session.store-type=redis
server.servlet.session.timeout=3600s
spring.session.redis.flush-mode=on-save
spring.session.redis.namespace=spring:session
spring.redis.host=localhost
spring.redis.port=6379
IndexController.java
:
@Controller
public class IndexController {
private AuthenticationManager authenticationManager;
IndexController(AuthenticationManager authenticationManager) {
this.authenticationManager = authenticationManager;
}
@GetMapping
ResponseEntity index(HttpServletRequest request, HttpSession session) {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
return new ResponseEntity<>(authentication.getPrincipal(), HttpStatus.OK);
}
@PostMapping("/login")
ResponseEntity login(@RequestBody LoginRequest loginRequest) {
String username = loginRequest.getUsername();
String password = loginRequest.getPassword();
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(username, password);
Authentication authentication = this.authenticationManager.authenticate(token);
return new ResponseEntity<>(authentication.getPrincipal(), HttpStatus.OK);
}
}
Config.java
:
@EnableGlobalMethodSecurity(prePostEnabled = true)
@EnableWebSecurity
@EnableRedisHttpSession
@Configuration
public class Config extends WebSecurityConfigurerAdapter {
@Autowired
private CustomUserDetailsService userDetailsService;
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService);
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.ALWAYS)
.and()
.csrf()
.disable()
.authorizeRequests()
.anyRequest()
.permitAll();
}
}
原来我忘了在login
方法中设置authentication
。这是正确的代码。
@PostMapping("/login")
ResponseEntity login(@RequestBody LoginRequest loginRequest) {
String username = loginRequest.getUsername();
String password = loginRequest.getPassword();
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(username, password);
Authentication authentication = this.authenticationManager.authenticate(token);
// vvv THIS vvv
SecurityContextHolder
.getContext()
.setAuthentication(authentication);
return new ResponseEntity<>(authentication.getPrincipal(), HttpStatus.OK);
}