在使用 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.eyjpc3mioijzchjpbmctc2vjdxjpdhktand0iiwic3ljoidxnlcm5hbwuilcjlehaioje3mdu0ndmyqxdwniiFw^motcaiwoodiwoodiwoo; eefqbid5dplhffzcvd7scmmt3f7rk7sk1i6kerpqi5ubdvaefnzsjq6vka5nadltsbqidfzogmoixjktfhsc5zrnyyrhikvnwcwb3wrgdd1gihaldfjktfhsc5zrnyyrhikvnwcwb3wrgdd1m zk3gqw42uecib9h1rrlkx9pdk7pf9rtfssfcwc-ntvismrycreco9rialqfydpdzeojimcbqveyboqfhn2woepgdm8mr5zsdhgdq e1ivsibbcj_0486zuzuqik>p25zsdhgd
安全性設定:#
@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中文網其他相關文章!