在使用 oauth 2.0 资源服务器 jwt 时,有时会遇到权限(授权)问题。这是许多开发人员在开发过程中经常遇到的一个挑战。oauth 2.0 是一种用于授权的开放标准,它允许用户授权第三方应用访问其受保护的资源。jwt(json web token)是一种用于在网络应用之间传递声明的方式。然而,在实践中,可能会出现一些权限问题,比如授权失败、无法获取访问令牌等。本文将针对这些问题进行解析,并提供一些解决方案,帮助开发人员更好地使用 oauth 2.0 资源服务器 jwt。
我正在尝试使用 oauth 2.0 资源服务器 jwt 在一个简单的应用程序中使用 jwt 配置访问授权。
整个身份验证部分工作正常,但我在授权方面遇到问题。即使令牌中存在正确的权限,所有受保护的端点也会给出 403 forbidden 错误。
我尝试使用默认范围(scope_)属性并将配置更改为角色(role_),但问题仍然存在。
有谁知道怎么解决吗?
完整源代码: https://github.com/gustavosc1/spring-security-jwt
生成令牌示例: eyjhbgcioijsuzi1nij9.eyjpc3mioijzchjpbmctc2vjdxjpdhktand0iiwic3viijoidxnlcm5hbwuilcjlehaioje3mdu0ndmyotqsimlhdci6mtcwntqwnzi5ncwicm9szxmi oijst0xfx0fetuloin0.peivwrthx_7mr6eefqbid5dplhffzcvd7scmmt3f7rk7sk1i6kerpqi5ubdvaefnzsjq6vka5nadltsbqidfzogmoixjktfhsc5zrnyyrhikvnwcwb3wrgdd1ezgihaldfjxwxsyypau njwdxznirkl93e6mg1uao5piy9p-9yp8jer7o31wkdr1coskzk3gqw42uecib9h1rrlkx9pdk7pf9rtfssfcwc-ntvismrycreco9rialqfydpdzeojimcbqveyboqfhn2woepgdm8mr5zsdhgdq e1ivsibfbcj_0486zuqiksxp2kniljhl2b5qnan07fjpvslk--ccsg
安全配置:
@configuration
@enablewebsecurity
//@enablemethodsecurity(prepostenabled = true)
public class securityconfig {
@value("${jwt.public.key}")
private rsapublickey key;
@value("${jwt.private.key}")
private rsaprivatekey priv;
@bean
securityfilterchain filterchain(httpsecurity http) throws exception {
http.csrf(csrf -> csrf.disable())
.authorizehttprequests(
auth -> auth
.requestmatchers("/authenticate").permitall()
.requestmatchers("/register").permitall()
.requestmatchers("/private").hasanyrole("admin"))
.httpbasic(customizer.withdefaults())
// https://docs-spring-io.translate.goog/spring-security/reference/servlet/oauth2/resource-server/jwt.html?_x_tr_sl=en&_x_tr_tl=pt&_x_tr_hl=pt-br&_x_tr_pto=sc
.oauth2resourceserver(
conf -> conf.jwt(
jwt -> jwt.decoder(jwtdecoder())
.jwtauthenticationconverter(jwtauthenticationconverter())));
return http.build();
}
@bean
public jwtauthenticationconverter jwtauthenticationconverter() {
jwtgrantedauthoritiesconverter grantedauthoritiesconverter = new jwtgrantedauthoritiesconverter();
grantedauthoritiesconverter.setauthoritiesclaimname("roles");
grantedauthoritiesconverter.setauthorityprefix("role_");
jwtauthenticationconverter jwtauthenticationconverter = new jwtauthenticationconverter();
jwtauthenticationconverter.setjwtgrantedauthoritiesconverter(grantedauthoritiesconverter);
return jwtauthenticationconverter;
}
@bean
jwtdecoder jwtdecoder() {
return nimbusjwtdecoder.withpublickey(this.key).build();
}
@bean
jwtencoder jwtencoder() {
jwk jwk = new rsakey.builder(this.key).privatekey(this.priv).build();
jwksource<securitycontext> jwks = new immutablejwkset<>(new jwkset(jwk));
return new nimbusjwtencoder(jwks);
}
@bean
passwordencoder passwordencoder() {
return new bcryptpasswordencoder();
}
}userdetailsserviceimpl:
@service
public class userdetailsserviceimpl implements userdetailsservice {
private final userrepository userrepository;
public userdetailsserviceimpl(userrepository userrepository) {
this.userrepository = userrepository;
}
@override
public userdetails loaduserbyusername(string username) throws usernamenotfoundexception {
optional<user> useroptional = userrepository.findbyusername(username);
user user = useroptional.orelsethrow(() -> new usernamenotfoundexception("user not found with username: " + username));
return new userauthenticated(user.getusername(), user.getpassword());
}
}用户已验证:
public class userauthenticated implements userdetails {
private string username;
private string password;
public userauthenticated(string username, string password) {
this.username = username;
this.password = password;
}
@override
public string getusername() {
return username;
}
@override
public string getpassword() {
return password;
}
@override
public collection<? extends grantedauthority> getauthorities() {
return list.of(() -> "role_admin");
}
@override
public boolean isaccountnonexpired() {
return true;
}
@override
public boolean isaccountnonlocked() {
return true;
}
@override
public boolean iscredentialsnonexpired() {
return true;
}
@override
public boolean isenabled() {
return true;
}
}jwtservice:
@service
public class jwtservice {
private final jwtencoder encoder;
public jwtservice(jwtencoder encoder) {
this.encoder = encoder;
}
public string generatetoken(authentication authentication) {
instant now = instant.now();
long expiry = 36000l;
string scope = authentication
.getauthorities().stream()
.map(grantedauthority::getauthority)
.collect(collectors
.joining(" "));
jwtclaimsset claims = jwtclaimsset.builder()
.issuer("spring-security-jwt")
.issuedat(now)
.expiresat(now.plusseconds(expiry))
.subject(authentication.getname())
.claim("roles", scope)
.build();
return encoder.encode(
jwtencoderparameters.from(claims))
.gettokenvalue();
}
}私人控制器:
@RestController
@RequestMapping("private")
public class PrivateController {
@GetMapping
//@PreAuthorize("hasAuthority('ROLE_ADMIN')")
public String getMessage() {
return "Hello from private API controller";
}
}已生成提供的令牌,并将 roles 字段设置为 ROLE_ADMIN。在 jwtAuthenticationConverter() 中,您尝试将 setAuthorityPrefix 与 ROLE 一起使用,导致 ROLE_ROLE_ADMIN。
要纠正此问题,请将该行修改为 grantedAuthoritiesConverter.setAuthorityPrefix("");。
进行此调整后,问题应该得到解决。如果您遇到任何其他问题,请告诉我。
注意:
如果省略此步骤,默认前缀将为 SCOPE,导致您的角色变为 SCOPE_ROLE_ADMIN。
以上就是使用 OAuth 2.0 资源服务器 JWT 时出现权限(授权)问题的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号