Rumah  >  Artikel  >  Isu Kebenaran (Kebenaran) Menggunakan Pelayan Sumber OAuth 2.0 JWT

Isu Kebenaran (Kebenaran) Menggunakan Pelayan Sumber OAuth 2.0 JWT

WBOY
WBOYke hadapan
2024-02-13 15:51:09973semak imbas

Apabila menggunakan OAuth 2.0 Resource Server JWT, anda kadangkala menghadapi masalah kebenaran (kebenaran). Ini adalah cabaran yang sering dihadapi oleh ramai pembangun semasa proses pembangunan. OAuth 2.0 ialah piawaian terbuka untuk kebenaran yang membenarkan pengguna membenarkan aplikasi pihak ketiga mengakses sumber dilindungi mereka. JWT (JSON Web Token) ialah satu cara untuk meluluskan tuntutan antara aplikasi web. Walau bagaimanapun, dalam amalan, beberapa masalah kebenaran mungkin berlaku, seperti kegagalan kebenaran, kegagalan untuk mendapatkan token akses, dsb. Artikel ini akan menganalisis isu ini dan menyediakan beberapa penyelesaian untuk membantu pembangun menggunakan pelayan sumber OAuth 2.0 JWT dengan lebih baik.

Kandungan soalan

Saya cuba mengkonfigurasi kebenaran akses menggunakan pelayan sumber oauth 2.0 jwt dalam aplikasi mudah.

Seluruh bahagian pengesahan berfungsi dengan baik, tetapi saya menghadapi masalah dengan kebenaran. Semua titik akhir yang dilindungi memberikan 403 forbidden ralat walaupun kebenaran yang betul terdapat dalam token.

Saya cuba menggunakan atribut skop lalai (scope_) dan menukar konfigurasi kepada peranan (role_) tetapi masalah berterusan.

Ada sesiapa tahu cara menyelesaikannya?

Kod sumber penuh: https://github.com/gustavosc1/spring-security-jwt

Jana contoh token: eyjhbgcioijsuzi1nij9.eyjpc3mioijzchjpbmctc2vjdxjpdhktand0iiwic3viijoidxnlcm5hbwuilcjlehaioje3mdu0ndmyotqsimtlhdcm x0fe tuloin0.peivwrthx_7mr6eefqbid5dplhffzcvd7scmmt3f7rk7sk1i6kerpqi5ubdvaefnzsjq6vka5nadltsbqidfzogmoixjktfhsc5zrnyyrhikvnwcwb3wrgfjxzwdd1wrgfjxzwk a b5qnan07fjpvslk--ccsg

Konfigurasi keselamatan:

@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());
  }

}

Pengguna disahkan:

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();
  }

}

Pengawal Persendirian:

@RestController
@RequestMapping("private")
public class PrivateController {

  @GetMapping
  //@PreAuthorize("hasAuthority('ROLE_ADMIN')")
  public String getMessage() {
    return "Hello from private API controller";
  }
  
}

Penyelesaian

telah menjana token dan akan roles 字段设置为 ROLE_ADMIN。在 jwtAuthenticationConverter() 中,您尝试将 setAuthorityPrefixROLE 一起使用,导致 ROLE_ROLE_ADMIN yang disediakan.

Untuk membetulkan masalah ini, tukar talian kepada grantedAuthoritiesConverter.setAuthorityPrefix("");.

Selepas membuat pelarasan ini, masalah harus diselesaikan. Jika anda menghadapi sebarang masalah lain sila beritahu saya.

Perhatian:

Jika anda meninggalkan langkah ini, awalan lalai ialah SCOPE,导致您的角色变为 SCOPE_ROLE_ADMIN.

Atas ialah kandungan terperinci Isu Kebenaran (Kebenaran) Menggunakan Pelayan Sumber OAuth 2.0 JWT. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Artikel ini dikembalikan pada:stackoverflow.com. Jika ada pelanggaran, sila hubungi admin@php.cn Padam