带有 JWT 的 Spring Security OAuth2 重定向到登录页面
Posted
技术标签:
【中文标题】带有 JWT 的 Spring Security OAuth2 重定向到登录页面【英文标题】:Spring Security OAuth2 with JWT redirect to login page 【发布时间】:2020-01-12 21:55:17 【问题描述】:我使用 OAuth2 和 JWT 创建了 Spring Security 应用程序。当它运行时,我得到一个登录页面。
下面我提到了pom.xml
文件。
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.0.RELEASE</version>
</parent>
<groupId>com.java.oauth</groupId>
<artifactId>AuthorizationWithOauth2nJWT</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>AuthorizationWithOauth2nJWT</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.security.oauth</groupId>
<artifactId>spring-security-oauth2</artifactId>
<version>2.0.10.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-jwt</artifactId>
<version>1.0.10.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</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-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
下面提到了AuthorizationServerConfig.java
文件。
@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter
private String clientId = "client-id";
private String clientSecret = "my-secret";
@Autowired
@Qualifier("authenticationManagerBean")
private AuthenticationManager getauthenticationManager;
@Bean
public JwtAccessTokenConverter tokenEnhancer()
JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
converter.setSigningKey("123");
return converter;
@Bean
public JwtTokenStore tokenStore()
return new JwtTokenStore(tokenEnhancer());
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception
endpoints.authenticationManager(getauthenticationManager).tokenStore(tokenStore())
.accessTokenConverter(tokenEnhancer());
@Override
public void configure(AuthorizationServerSecurityConfigurer security) throws Exception
security
.tokenKeyAccess("permitAll()")
.checkTokenAccess("isAuthenticated()");
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception
clients.inMemory()
.withClient(clientId)
.secret(clientSecret)
.scopes("read", "write", "trust")
.authorizedGrantTypes("password", "authorization_code", "refresh_token", "implicit")
.authorities("ROLE_CLIENT", "ROLE_TRUSTED_CLIENT")
.accessTokenValiditySeconds(20000)
.refreshTokenValiditySeconds(20000);
这是 ResourceServerConfig.java 文件。
@Configuration
@EnableResourceServer
@Order(100)
public class ResourceServerConfig extends ResourceServerConfigurerAdapter
@Override
public void configure(HttpSecurity http) throws Exception
http.csrf().disable();
http.requestMatchers().antMatchers("/oauth/**")
.and()
.authorizeRequests()
.antMatchers("/oauth/**").authenticated();
这是 SecurityConfig.java 文件。
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter
@Bean
public PasswordEncoder encoder()
return new BCryptPasswordEncoder();
@Override
protected void configure(HttpSecurity http) throws Exception
http
.authorizeRequests()
.antMatchers("/oauth/token").permitAll()
.antMatchers("/getuser").permitAll()
.anyRequest().authenticated()
.and()
.formLogin().permitAll()
.and()
.csrf().disable();
@Override
@Bean
public AuthenticationManager authenticationManagerBean() throws Exception
return super.authenticationManagerBean();
下面我提到了application.yml文件
server:
port: 8081
spring:
security:
user:
name: test
password: test
security:
oauth2:
resource:
filter-order: 3
我使用 postman 来执行 API。授权和请求正文定义如下图。
执行 API 后,我收到以下响应,状态码为 200。
<html>
<head>
<title>Login Page</title>
</head>
<body onload='document.f.username.focus();'>
<h3>Login with Username and Password</h3>
<form name='f' action='/login' method='POST'>
<table>
<tr>
<td>User:</td>
<td><input type='text' name='username' value=''></td>
</tr>
<tr>
<td>Password:</td>
<td><input type='password' name='password'/></td>
</tr>
<tr>
<td colspan='2'><input name="submit" type="submit" value="Login"/></td>
</tr>
</table>
</form>
</body>
</html>
非常感谢任何解决此问题的帮助或解决方法。
【问题讨论】:
你真正想要什么?您是否想像使用 API 一样获取访问令牌/ID 令牌(例如:- 没有登录页面)? @KavinduDodanduwa 是的,我想要没有登录页面的访问令牌和刷新令牌。 【参考方案1】:OP 真正想要的是获得一个访问令牌,就好像它是从 API 获得的一样。
为此,OAuth 2.0 定义了两种授权类型
-
Client Credentials Grant
Resource Owner Password Credentials Grant
在这两种情况下,您都会跳过登录屏幕并调用令牌端点来获取访问令牌。请阅读 RFC(上面的链接)以了解您应该在何时何地采用这些授权类型。
我不是 Spring 专家,因此我在这里链接到在网上找到的教程,该教程解释了 Spring 的两种授权。
password-grant client-grant【讨论】:
这个链接对我很有帮助。谢谢 我的问题仍然没有解决。我尽力了,但我没有任何快乐的道路 @LakshithaGihan 你现在面对什么?一个小小的解释可以让知道 $subject 的人帮助你。 @Kavindu 还是同样的问题。我认为我的用户名和密码没有编码。因为我在另一个项目的 application.yml 文件中进行了所有配置,并且工作正常。但这不是一个好习惯。 @LakshithaGihan 你检查过 Postman 的编码支持吗?例如更改参数以作为表单帖子或 URL 编码发送?【参考方案2】:我添加了 UserConfig.java 类并添加了以下代码。
PasswordEncoder passwordEncoder = PasswordEncoderFactories.createDelegatingPasswordEncoder();
@Override
public void init(AuthenticationManagerBuilder auth) throws Exception
auth
.inMemoryAuthentication()
.withUser("test")
.password(passwordEncoder.encode("test123"))
.roles("USER","ADMIN","MANAGER")
.authorities("CAN_READ","CAN_WRITE","CAN_DELETE");
在 AuthorizationServerConfig.java 类中,删除 public void configure(ClientDetailsServiceConfigurer clients) 方法并添加以下代码。
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception
clients.inMemory()
.withClient("client")
.secret(passwordEncoder.encode("password"))
.scopes("READ", "WRITE")
.authorizedGrantTypes("password", "refresh_token", "id_token");
我在 application.yml 文件中删除了以下配置
spring:
security:
user:
name: test
password: test
下图中提到的成功响应。
【讨论】:
以上是关于带有 JWT 的 Spring Security OAuth2 重定向到登录页面的主要内容,如果未能解决你的问题,请参考以下文章
带有 JWT 令牌的 Spring Security 在每个请求上加载 spring UserDetails 对象
带有 JWT 令牌的 Spring Security 和 Websocket
带有 JWT 的 Spring Security Oauth2 真的是无状态的吗?
带有 JWT 的 Spring Security OAuth2 重定向到登录页面