[英]Spring OAuth2 Authorization: Access Denied
I am pretty new to spring security & OAuth2.我对 spring 安全和 OAuth2 很陌生。 As a part of the learning I am trying to set up an OAuth2 Authorization server and protect a REST end point from unauthorized access.
作为学习的一部分,我尝试设置OAuth2 授权服务器并保护 REST 端点免受未经授权的访问。
My resource server contains couple of end points, with the following Authorization.我的资源服务器包含几个端点,具有以下授权。
/products : only user with Authority='ROLE_PRODUCT_USER' and scope='read' can access this endpoint
/addProduct : only user with Authority='ROLE_PRODUCT_ADMIN' and scope='write' can access this endpoint
ISSUE: Access denied while trying to access the end points using postman and grant_type="password"
问题:尝试使用 postman 和 grant_type="password" 访问端点时访问被拒绝
CODE代码
Resource Server
资源服务器
ProductController.java产品控制器.java
@RestController
public class ProductController {
@Autowired
private ProductService productService;
@PreAuthorize("#oauth2.hasScope('read') and hasAuthority('ROLE_PRODUCT_USER')")
@GetMapping("/products")
public ResponseEntity<List<Product>> getAllProducts() {
return new ResponseEntity<List<Product>>(productService.getAllProducts(), HttpStatus.OK);
}
@PreAuthorize("#oauth2.hasScope('write') and hasAuthority('ROLE_PRODUCT_ADMIN')")
@PostMapping("/addproduct")
public ResponseEntity<Product> addProduct(@RequestBody Product product) {
return new ResponseEntity<Product>(productService.addProduct(product), HttpStatus.OK);
}
}
OAuth config in Resource Server资源服务器中的 OAuth 配置
security:
oauth2:
resource:
user-info-uri: http://localhost:9090/user
Authorization Server
授权服务器
Main Class where the user-info-uri is implemented实现 user-info-uri 的主类
import java.security.Principal;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@SpringBootApplication
@EnableAuthorizationServer
@EnableResourceServer
@RestController
public class OAuthAuthorizationServerApplication {
public static void main(String[] args) {
SpringApplication.run(OAuthAuthorizationServerApplication.class, args);
}
@GetMapping("/user")
public Principal user(Principal user) {
System.out.println(user);
return user;
}
}
Database oauth_client_details
数据库oauth_client_details
mysql> select * from oauth_client_details where client_id in ('reader','writer'); mysql> select * from oauth_client_details where client_id in ('reader','writer');
+-----------+--------------+----------------------------------------------------------------------+------------+--------------------------------------------------------------+----------------------------+--------------------+-----------------------+------------------------+------------------------+-------------+
| client_id | resource_ids | client_secret | scope | authorized_grant_types | web_server_redirect_uri | authorities | access_token_validity | refresh_token_validity | additional_information | autoapprove |
+-----------+--------------+----------------------------------------------------------------------+------------+--------------------------------------------------------------+----------------------------+--------------------+-----------------------+------------------------+------------------------+-------------+
| reader | product_api | {bcrypt}removed | read | client_credentials,password,refersh_token,authorization_code | http://localhost:8080/home | ROLE_PRODUCT_USER | 10800 | 2592000 | NULL | NULL |
| writer | product_api | {bcrypt}removed | read,write | client_credentials,password,refersh_token,authorization_code | http://localhost:8080/home | ROLE_PRODUCT_ADMIN | 10800 | 2592000 | NULL | NULL |
+-----------+--------------+----------------------------------------------------------------------+------------+--------------------------------------------------------------+----------------------------+--------------------+-----------------------+------------------------+------------------------+-------------+
ANALYSIS分析
{authorities=[{id=4, authority=ROLE_PRODUCT_USER}], details={remoteAddress=127.0.0.1, sessionId=null, tokenValue=2f54e499-e47a-45fe-a6f6-e4c9593f9841, tokenType=Bearer, decodedDetails=null}, authenticated=true, userAuthentication={authorities=[{id=4, authority=ROLE_PRODUCT_USER}], details={clinet_id=reader, grant_type=password, username=product_user}, authenticated=true, principal={password=null, username=product_user, authorities=[{id=4, authority=ROLE_PRODUCT_USER}], accountNonExpired=true, accountNonLocked=true, credentialsNonExpired=true, enabled=true}, credentials=null, name=product_user}, credentials=, oauth2Request={clientId=reader, scope=[read] , requestParameters={clinet_id=reader, grant_type=password, username=product_user}, resourceIds=[product_api], authorities=[{authority=ROLE_PRODUCT_USER}], approved=true, refresh=false, redirectUri=null, responseTypes=[], extensions={}, grantType=password, refreshTokenRequest=null}, principal={password=null, username=product_user, author
{authorities=[{id=4, authority=ROLE_PRODUCT_USER}], details={remoteAddress=127.0.0.1, sessionId=null, tokenValue=2f54e499-e47a-45fe-a6f6-e4c9593f9841, tokenType=Bearer, decodedDetails=null} =true, userAuthentication={authorities=[{id=4, authority=ROLE_PRODUCT_USER}], details={clinet_id=reader, grant_type=password, username=product_user},authenticated=true, principal={password=null, username=product_user , authority=[{id=4, authority=ROLE_PRODUCT_USER}], accountNonExpired=true, accountNonLocked=true, credentialsNonExpired=true, enabled=true}, credentials=null, name=product_user}, credentials=, oauth2Request={clientId=reader , scope=[read] , requestParameters={clinet_id=reader, grant_type=password, username=product_user}, resourceIds=[product_api], authority=[{authority=ROLE_PRODUCT_USER}],approved=true, refresh=false, redirectUri=null , responseTypes=[], extensions={}, grantType=password, refreshTokenRequest=null}, principal={password=null, username=product_user, author ities=[{id=4, authority=ROLE_PRODUCT_USER}], accountNonExpired=true, accountNonLocked=true, credentialsNonExpired=true, enabled=true}, clientOnly=false, name=product_user}
ities=[{id=4, authority=ROLE_PRODUCT_USER}], accountNonExpired=true, accountNonLocked=true, credentialsNonExpired=true, enabled=true}, clientOnly=false, name=product_user}
But it is not persisted while creating an OAuth2Request in UserInfoTokenServices.extractAuthentication()但是在 UserInfoTokenServices.extractAuthentication() 中创建 OAuth2Request 时它不会持久化
private OAuth2Authentication extractAuthentication(Map<String, Object> map) { Object principal = getPrincipal(map); List<GrantedAuthority> authorities = this.authoritiesExtractor .extractAuthorities(map); OAuth2Request request = new OAuth2Request(null, this.clientId, null, true, null, null, null, null, null); UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken( principal, "N/A", authorities); token.setDetails(map); return new OAuth2Authentication(request, token); }
Here the 5th paramter is a Set of string that represents scopes, which is passed as null!这里的第 5 个参数是一个代表作用域的字符串 Set ,它作为 null 传递!
OAuth2Request request = new OAuth2Request(null, this.clientId, null, true, null, null, null, null, null);
OAuth2Request request = new OAuth2Request(null, this.clientId, null, true, null, null, null, null, null);
Am i missing any configuration here ?我在这里缺少任何配置吗?
As you already noticed yourself and as mentioned in the Issue #5096 , the default UserInfoTokenServices
does not support scopes, hence #oauth2.hasScope
functionality.正如您已经注意到自己并在问题 #5096 中提到的,默认的
UserInfoTokenServices
不支持范围,因此#oauth2.hasScope
功能。 A possible solution would be to implement a custom ResourceServerTokenServices
.一个可能的解决方案是实现自定义
ResourceServerTokenServices
。
I also want to draw your attention to the fact that the Spring Security OAuth project is deprecated and is not recommended for use.我还想提请您注意Spring Security OAuth项目已被弃用且不推荐使用的事实。
@Renjith Please refer to this question, I answered it there, let me know if u face any other challenges @Renjith 请参考这个问题,我在那里回答了,如果你面临任何其他挑战,请告诉我
How to set user authorities from user claims return by an oauth server in spring security 如何在spring security中从oauth服务器返回的用户声明中设置用户权限
Another thing in your @RestController
m use this @PreAuthorize("hasRole('ROLE_PRODUCT_USER')")
and not @RestController
另一件事是使用这个@PreAuthorize("hasRole('ROLE_PRODUCT_USER')")
而不是
@PreAuthorize("#oauth2.hasScope('read') and hasAuthority('ROLE_PRODUCT_USER')")
Since the GrantedAuthoritiesMapper
is returning a list or set of GrantedAuthority
, which your authorization server is returning the authenticated user authorities as ROLES, then you need to use the @PreAuthorize("hasRole('ROLE_PRODUCT_USER')")
so it can use the ROLES
prepend由于
GrantedAuthoritiesMapper
正在返回一个列表或一组GrantedAuthority
,您的授权服务器将经过身份验证的用户权限作为 ROLES 返回,那么您需要使用@PreAuthorize("hasRole('ROLE_PRODUCT_USER')")
以便它可以使用ROLES
前置
Also refer to https://docs.spring.io/spring-security/site/docs/5.0.7.RELEASE/reference/html/oauth2login-advanced.html另请参阅https://docs.spring.io/spring-security/site/docs/5.0.7.RELEASE/reference/html/oauth2login-advanced.html
for more details on customizing the GrantedAuthoritiesMapper
有关自定义
GrantedAuthoritiesMapper
更多详细信息
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.