如何在springboot配置文件中设置UsernamePasswordAuthenticationFilter下的postOnly为false
时间: 2023-12-10 15:42:58 浏览: 20
在Spring Boot中,可以通过在application.properties或application.yml配置文件中设置spring.security.filter.order属性来控制过滤器链的顺序。要将UsernamePasswordAuthenticationFilter的postOnly属性设置为false,可以在配置文件中添加以下内容:
```
spring.security.filter.order=UsernamePasswordAuthenticationFilter
spring.security.filter.usernamePassword.postOnly=false
```
这将使Spring Security在过滤器链中将UsernamePasswordAuthenticationFilter的顺序设置为第一位,并且将postOnly属性设置为false,即允许使用GET请求进行身份验证。注意,这只是一个示例,你需要根据你的实际情况进行调整。
相关问题
springboot配置jwt
在Spring Boot应用程序中,配置JWT的步骤如下:
1. 添加相关的依赖:在pom.xml文件中添加以下依赖:
```
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.1</version>
</dependency>
```
2. 创建一个JWT工具类:该类用于处理JWT的生成和验证。以下是一个简单的示例:
```
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Component;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Function;
@Component
public class JwtTokenUtil {
private static final long JWT_TOKEN_VALIDITY = 5 * 60 * 60;
@Value("${jwt.secret}")
private String secret;
public String getUsernameFromToken(String token) {
return getClaimFromToken(token, Claims::getSubject);
}
public Date getExpirationDateFromToken(String token) {
return getClaimFromToken(token, Claims::getExpiration);
}
public <T> T getClaimFromToken(String token, Function<Claims, T> claimsResolver) {
final Claims claims = getAllClaimsFromToken(token);
return claimsResolver.apply(claims);
}
private Claims getAllClaimsFromToken(String token) {
return Jwts.parser().setSigningKey(secret).parseClaimsJws(token).getBody();
}
private Boolean isTokenExpired(String token) {
final Date expiration = getExpirationDateFromToken(token);
return expiration.before(new Date());
}
public String generateToken(UserDetails userDetails) {
Map<String, Object> claims = new HashMap<>();
return doGenerateToken(claims, userDetails.getUsername());
}
private String doGenerateToken(Map<String, Object> claims, String subject) {
final Date createdDate = new Date();
final Date expirationDate = new Date(createdDate.getTime() + JWT_TOKEN_VALIDITY * 1000);
return Jwts.builder().setClaims(claims).setSubject(subject)
.setIssuedAt(createdDate).setExpiration(expirationDate)
.signWith(SignatureAlgorithm.HS512, secret).compact();
}
public Boolean validateToken(String token, UserDetails userDetails) {
final String username = getUsernameFromToken(token);
return (username.equals(userDetails.getUsername()) && !isTokenExpired(token));
}
}
```
3. 创建一个JWT过滤器:该过滤器用于验证请求的JWT。以下是一个简单的示例:
```
import io.jsonwebtoken.ExpiredJwtException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.stereotype.Component;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@Component
public class JwtRequestFilter extends OncePerRequestFilter {
@Autowired
private UserDetailsService userDetailsService;
@Autowired
private JwtTokenUtil jwtTokenUtil;
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
throws ServletException, IOException {
final String requestTokenHeader = request.getHeader("Authorization");
String username = null;
String jwtToken = null;
if (requestTokenHeader != null && requestTokenHeader.startsWith("Bearer ")) {
jwtToken = requestTokenHeader.substring(7);
try {
username = jwtTokenUtil.getUsernameFromToken(jwtToken);
} catch (IllegalArgumentException e) {
logger.error("Unable to get JWT Token");
} catch (ExpiredJwtException e) {
logger.error("JWT Token has expired");
}
} else {
logger.warn("JWT Token does not begin with Bearer String");
}
if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
UserDetails userDetails = this.userDetailsService.loadUserByUsername(username);
if (jwtTokenUtil.validateToken(jwtToken, userDetails)) {
UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(
userDetails, null, userDetails.getAuthorities());
usernamePasswordAuthenticationToken
.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken);
}
}
chain.doFilter(request, response);
}
}
```
4. 在Spring Boot应用程序中配置JWT:您需要在应用程序配置文件中添加以下属性:
```
jwt.secret=your_secret_key_here
```
5. 在Spring Boot应用程序中启用JWT:您需要在Spring Boot应用程序中启用JWT。以下是一个简单的示例:
```
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
@SpringBootApplication(exclude = {SecurityAutoConfiguration.class})
@EnableWebSecurity
public class Application extends WebSecurityConfigurerAdapter {
@Autowired
private JwtAuthenticationEntryPoint jwtAuthenticationEntryPoint;
@Autowired
private UserDetailsService jwtUserDetailsService;
@Autowired
private JwtRequestFilter jwtRequestFilter;
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(jwtUserDetailsService).passwordEncoder(passwordEncoder());
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Bean
public JwtAuthenticationEntryPoint jwtAuthenticationEntryPointBean() throws Exception {
return new JwtAuthenticationEntryPoint();
}
@Bean
public JwtRequestFilter jwtRequestFilterBean() throws Exception {
return new JwtRequestFilter();
}
@Override
@Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
@Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity.csrf().disable()
.authorizeRequests().antMatchers("/authenticate").permitAll().
anyRequest().authenticated().and().
exceptionHandling().authenticationEntryPoint(jwtAuthenticationEntryPoint).and().sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS);
httpSecurity.addFilterBefore(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class);
}
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
```
以上就是在Spring Boot应用程序中配置JWT的基本步骤。
在springboot框架下,结合security、jwt写一套登录、认证、鉴权
好的,下面介绍一下如何使用Spring Boot、Spring Security和JWT实现登录、认证和鉴权。
1. 添加依赖
在 `pom.xml` 文件中添加以下依赖:
```xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-api</artifactId>
<version>0.11.2</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-impl</artifactId>
<version>0.11.2</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-jackson</artifactId>
<version>0.11.2</version>
<scope>runtime</scope>
</dependency>
```
2. 配置Spring Security
在 `application.yml` 文件中配置 Spring Security:
```yaml
spring:
security:
user:
name: admin
password: admin
```
这里定义了一个用户名为 admin,密码为 admin 的用户。
3. 实现Controller
实现一个简单的Controller,用于演示登录、认证和鉴权:
```java
@RestController
public class HelloWorldController {
@GetMapping("/hello")
public String hello() {
return "Hello World";
}
@GetMapping("/admin")
public String admin() {
return "Hello Admin";
}
}
```
其中,`/hello` 是一个公共的接口,不需要鉴权;`/admin` 是需要鉴权的接口,只有管理员才能访问。
4. 实现认证和鉴权逻辑
在 `SecurityConfig` 类中,实现认证和鉴权逻辑:
```java
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private UserDetailsService userDetailsService;
@Autowired
private JwtTokenProvider jwtTokenProvider;
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.authorizeRequests()
.antMatchers("/hello").permitAll()
.antMatchers("/admin").hasRole("ADMIN")
.and()
.apply(new JwtConfigurer(jwtTokenProvider));
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder(12);
}
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
}
}
```
其中,`JwtTokenProvider` 是一个自定义的类,用于生成和验证 JWT。
5. 实现JWT逻辑
在 `JwtTokenProvider` 类中,实现JWT逻辑:
```java
@Component
public class JwtTokenProvider {
private static final String SECRET_KEY = "mySecretKey";
private static final long EXPIRATION_TIME = 864_000_000; // 10 days
public String createToken(String username, List<String> roles) {
Claims claims = Jwts.claims().setSubject(username);
claims.put("roles", roles);
Date now = new Date();
Date expiration = new Date(now.getTime() + EXPIRATION_TIME);
return Jwts.builder()
.setClaims(claims)
.setIssuedAt(now)
.setExpiration(expiration)
.signWith(SignatureAlgorithm.HS256, SECRET_KEY)
.compact();
}
public boolean validateToken(String token) {
try {
Jwts.parser().setSigningKey(SECRET_KEY).parseClaimsJws(token);
return true;
} catch (JwtException | IllegalArgumentException e) {
throw new JwtAuthenticationException("JWT token is invalid or expired", e);
}
}
public Authentication getAuthentication(String token) {
UserDetails userDetails = User.builder()
.username(getUsername(token))
.password("")
.authorities(getRoles(token).stream().map(SimpleGrantedAuthority::new).collect(Collectors.toList()))
.build();
return new UsernamePasswordAuthenticationToken(userDetails, "", userDetails.getAuthorities());
}
private String getUsername(String token) {
return Jwts.parser().setSigningKey(SECRET_KEY).parseClaimsJws(token).getBody().getSubject();
}
private List<String> getRoles(String token) {
return (List<String>) Jwts.parser().setSigningKey(SECRET_KEY).parseClaimsJws(token).getBody().get("roles");
}
}
```
6. 实现认证逻辑
在 `UserDetailsServiceImpl` 类中,实现认证逻辑:
```java
@Service
public class UserDetailsServiceImpl implements UserDetailsService {
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
if (username.equals("admin")) {
return User.builder()
.username("admin")
.password("$2a$12$EIlCPMzjwB2s2sG1c8yvIuVpT0X1OgW3T8ZvTJjqc5wU1bh6q3K6C")
.roles("ADMIN")
.build();
} else {
throw new UsernameNotFoundException("User not found");
}
}
}
```
这里返回一个用户名为 admin,密码为 admin(经过 BCrypt 加密)的用户。
7. 实现JWT过滤器
在 `JwtTokenFilter` 类中,实现JWT过滤器:
```java
public class JwtTokenFilter extends OncePerRequestFilter {
@Autowired
private JwtTokenProvider jwtTokenProvider;
@Override
protected void doFilterInternal(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, FilterChain filterChain) throws ServletException, IOException {
String token = getToken(httpServletRequest);
if (token != null && jwtTokenProvider.validateToken(token)) {
Authentication auth = jwtTokenProvider.getAuthentication(token);
SecurityContextHolder.getContext().setAuthentication(auth);
}
filterChain.doFilter(httpServletRequest, httpServletResponse);
}
private String getToken(HttpServletRequest request) {
String authHeader = request.getHeader("Authorization");
if (authHeader != null && authHeader.startsWith("Bearer ")) {
return authHeader.substring(7);
}
return null;
}
}
```
8. 实现JWT配置类
最后,在 `JwtConfigurer` 类中,实现JWT配置类:
```java
public class JwtConfigurer extends SecurityConfigurerAdapter<DefaultSecurityFilterChain, HttpSecurity> {
private JwtTokenProvider jwtTokenProvider;
public JwtConfigurer(JwtTokenProvider jwtTokenProvider) {
this.jwtTokenProvider = jwtTokenProvider;
}
@Override
public void configure(HttpSecurity http) {
JwtTokenFilter customFilter = new JwtTokenFilter();
http.addFilterBefore(customFilter, UsernamePasswordAuthenticationFilter.class);
}
}
```
9. 测试
使用 Postman 分别测试 `/hello` 和 `/admin` 接口,可以发现:
- 访问 `/hello` 接口时,不需要鉴权,返回结果为 `Hello World`;
- 访问 `/admin` 接口时,需要鉴权,如果使用正确的用户名和密码(admin/admin),返回结果为 `Hello Admin`;否则,返回 401 Unauthorized 错误。
至此,登录、认证和鉴权的实现就完成了。