Oauth 2---권한 수여 코드 모드(authorization코드 프로 세 스
17869 단어 자바
1.인증 코드 획득:
권한 수여 서버/oath/authorize 터미널 에 접근:("implicit","authorizationcode")
GET: http://127.0.0.1:8080/oauth/authorize?client_id=client&response_type=code&redirect_uri=http://www.baidu.com
인자:
(1)response_type=code 반드시 지정 해 야 한다.
(2) client_id=client 클 라 이언 트 가 지정 해 야 합 니 다.
(3)redirect_uri=http://주소 재 설정 은 데이터 시트 와 일치 해 야 합 니 다.
결과:권한 수여 에 동의 하면 code=cown 42 로 돌아 가 redirect 로 이동 합 니 다.uri=http://www.baidu.com
과정:비교 clientid,및 redirecturi、scope、
핵심 클래스 와 관련:
(1)DefaultRedirectResolver:redirect_uri 주소 검사.
(2)Jdbc Authorization Code Services/InMemory Authorization Code Services:생 성 된 code 를 메모리 나 데이터베이스(oauth코드 테이블
(3)JdbcClient Details Service:표 oauthclient_details 는 client Details 정 보 를 읽 어서 검사 합 니 다.
(4)LoginUrl Authentication Entry Point:마지막 로그 인 시 예외 적 으로 ExceptionTranslation Filter doFilter()-LoginUrl Authentication Entry Point->에서 loginFromUrl 페이지 로 재 설정 합 니 다.
public class AuthorizationEndpoint extends AbstractEndpoint {
// 、 :
private AuthorizationCodeServices authorizationCodeServices = new InMemoryAuthorizationCodeServices();
private RedirectResolver redirectResolver = new DefaultRedirectResolver();
private UserApprovalHandler userApprovalHandler = new DefaultUserApprovalHandler();
private SessionAttributeStore sessionAttributeStore = new DefaultSessionAttributeStore();
private OAuth2RequestValidator oauth2RequestValidator = new DefaultOAuth2RequestValidator();
//
private String userApprovalPage = "forward:/oauth/confirm_access";
private String errorPage = "forward:/oauth/error";
// 、 :
@RequestMapping(value = "/oauth/authorize")
public ModelAndView authorize(Map model, @RequestParam Map parameters,SessionStatus sessionStatus, Principal principal) {
/*1. DefaultOAuth2RequestFactory.createAuthorizationRequest()
AuthorizationRequest request = new AuthorizationRequest();
client clietDetails
ClientDetails clientDetails = clientDetailsService.loadClientByClientId(clientId);
request.setResourceIdsAndAuthoritiesFromClientDetails(clientDetails);
*/
AuthorizationRequest authorizationRequest = getOAuth2RequestFactory().createAuthorizationRequest(parameters);
Set responseTypes = authorizationRequest.getResponseTypes();
//2. code
if (!responseTypes.contains("token") && !responseTypes.contains("code")) {
throw new UnsupportedResponseTypeException("Unsupported response types: " + responseTypes);
}
//3. clientId
if (authorizationRequest.getClientId() == null) {
throw new InvalidClientException("A client id must be provided");
}
try {
//4. isAuthenticated = ture, , ExceptionTranslationFilter doFilter()---》LoginUrlAuthenticationEntryPoint--》 loginFromUrl 。
if (!(principal instanceof Authentication) || !((Authentication) principal).isAuthenticated()) {
throw new InsufficientAuthenticationException(
"User must be authenticated with Spring Security before authorization can be completed.");
}
//5. clientDetails
ClientDetails client = getClientDetailsService().loadClientByClientId(authorizationRequest.getClientId());
//6. redirect_uri 。 :"implicit", "authorization_code"
String redirectUriParameter = authorizationRequest.getRequestParameters().get(OAuth2Utils.REDIRECT_URI);
String resolvedRedirect = redirectResolver.resolveRedirect(redirectUriParameter, client);
if (!StringUtils.hasText(resolvedRedirect)) {
throw new RedirectMismatchException(
"A redirectUri must be either supplied or preconfigured in the ClientDetails");
}
authorizationRequest.setRedirectUri(resolvedRedirect);
// 7。 Scope
oauth2RequestValidator.validateScope(authorizationRequest, client);
// 8.
authorizationRequest = userApprovalHandler.checkForPreApproval(authorizationRequest,
(Authentication) principal);
// TODO: is this call necessary?
boolean approved = userApprovalHandler.isApproved(authorizationRequest, (Authentication) principal);
authorizationRequest.setApproved(approved);
// 10. , 。
// (1) Code : code, InMemoryAuthorizationCodeServices( ) JdbcAuthorizationCodeServices( oauth_code)
if (authorizationRequest.isApproved()) {
if (responseTypes.contains("token")) {
return getImplicitGrantResponse(authorizationRequest);
}
if (responseTypes.contains("code")) {
return new ModelAndView(getAuthorizationCodeResponse(authorizationRequest,
(Authentication) principal));
}
}
//11. ,
model.put("authorizationRequest", authorizationRequest);
return getUserApprovalPageResponse(model, authorizationRequest, (Authentication) principal);
}
catch (RuntimeException e) {
sessionStatus.setComplete();
throw e;
}
}
2.접근 토 큰 가 져 오기:권한 수여 서버/oauth/token 터미널 에 접근
사용자 가 로그 인 한 상태 인지 확인 하고 access 로 돌아 가기token 형식.
Post:
http://localhost:8080/oauth/token?
grant_type=authorization_code&code=o4YrCS&client_id=pair &client_secret=secret&redirect_uri=http://baidu.com
인자:
(1)clientId:클 라 이언 트 id,매개 변 수 를 지정 하 는 동시에 Principal 도 일치 해 야 합 니 다.그렇지 않 으 면 InvalidClient 예외(필수)
(2)client_secret:클 라 이언 트 밀 스푼
(2)grant_type:권한 부여 형식 입 니 다.(반드시
(3)코드:권한 수여 코드(필수)
핵심 클래스:
(1)AuthorizationServerTokenServices/DefaultTokenServices:이러한 종류 에서 token 을 생 성하 고 새로 고치 고 가 져 옵 니 다.
(2)TokenStore:사용자 스스로 실현 코드 를 제공 합 니 다.
(3)클래스 포장 관계:AbstractEndpoint--->AuthorizationServerTokenServices(DefaultTokenServices)---TokenStore
@FrameworkEndpoint
public class TokenEndpoint extends AbstractEndpoint {
private OAuth2RequestValidator oAuth2RequestValidator = new DefaultOAuth2RequestValidator();
/**
* access_token
**/
@RequestMapping(value = "/oauth/token", method=RequestMethod.POST)
public ResponseEntity postAccessToken(Principal principal, @RequestParam
Map parameters) throws HttpRequestMethodNotSupportedException {
//1. , , ExceptionTranslationFilter doFilter()---》LoginUrlAuthenticationEntryPoint--》 loginFromUrl 。
if (!(principal instanceof Authentication)) {
throw new InsufficientAuthenticationException(
"There is no client authentication. Try adding an appropriate authentication filter.");
}
//2. ClientDetails 。
String clientId = getClientId(principal);
ClientDetails authenticatedClient = getClientDetailsService().loadClientByClientId(clientId);
TokenRequest tokenRequest = getOAuth2RequestFactory().createTokenRequest(parameters, authenticatedClient);
//2. clientId
if (clientId != null && !clientId.equals("")) {
if (!clientId.equals(tokenRequest.getClientId())) {
throw new InvalidClientException("Given client ID does not match authenticated client");
}
}
//3. Scope
if (authenticatedClient != null) {
oAuth2RequestValidator.validateScope(tokenRequest, authenticatedClient);
}
//4. GrantType: implicit
if (!StringUtils.hasText(tokenRequest.getGrantType())) {
throw new InvalidRequestException("Missing grant type");
}
if (tokenRequest.getGrantType().equals("implicit")) {
throw new InvalidGrantException("Implicit grant type not supported from token endpoint");
}
//5. authorization_code , AuthCode:AuthCode != null && grant_type = authorization_code
if (isAuthCodeRequest(parameters)) {
// The scope was requested or determined during the authorization step
if (!tokenRequest.getScope().isEmpty()) {
logger.debug("Clearing scope of incoming token request");
tokenRequest.setScope(Collections. emptySet());
}
}
// token: grant_type = refresh_token
if (isRefreshTokenRequest(parameters)) {
// A refresh token has its own default scopes, so we should ignore any added by the factory here.
tokenRequest.setScope(OAuth2Utils.parseParameterList(parameters.get(OAuth2Utils.SCOPE)));
}
//5. token,TokenGranter( ) OAuth2AccessToken。
OAuth2AccessToken token = getTokenGranter().grant(tokenRequest.getGrantType(), tokenRequest);
if (token == null) {
throw new UnsupportedGrantTypeException("Unsupported grant type: " + tokenRequest.getGrantType());
}
return getResponse(token);
}
public abstract class AbstractTokenGranter implements TokenGranter {
/**
* : token ( DefaultTokenServices )
**/
private final AuthorizationServerTokenServices tokenServices;
private final ClientDetailsService clientDetailsService;
private final OAuth2RequestFactory requestFactory;
private final String grantType;
}
OAuth2AccessToken {
public static String BEARER_TYPE = "Bearer";
public static String OAUTH2_TYPE = "OAuth2";
public static String ACCESS_TOKEN = "access_token";
public static String TOKEN_TYPE = "token_type";
public static String EXPIRES_IN = "expires_in";
public static String REFRESH_TOKEN = "refresh_token";
public static String SCOPE = "scope";
}
/**
* 1.TokenStore: , token
* 2. :(1) accessToken 、 (2)loadAuthentication()accessToken
* 3. :
* (1)AuthorizationServerTokenServices: accessToken 、 。
* (2)ResourceServerTokenServices: accessToken , tokenString---> OAuth2Authentication
*/
public class DefaultTokenServices implements AuthorizationServerTokenServices, ResourceServerTokenServices,
ConsumerTokenServices, InitializingBean {
//Token 、 。( )
private TokenStore tokenStore;
//ClientDetail
private ClientDetailsService clientDetailsService;
//Token
private TokenEnhancer accessTokenEnhancer;
// : token ,
private AuthenticationManager authenticationManager;
/**
* OAuth2AccessToken
*/
@Transactional
public OAuth2AccessToken createAccessToken(OAuth2Authentication authentication) throws AuthenticationException {
//1. tokenStore accessToken
OAuth2AccessToken existingAccessToken = tokenStore.getAccessToken(authentication);
OAuth2RefreshToken refreshToken = null;
//1.tokenStore accessToken , 。
if (existingAccessToken != null) {
if (existingAccessToken.isExpired()) {
if (existingAccessToken.getRefreshToken() != null) {
refreshToken = existingAccessToken.getRefreshToken();
tokenStore.removeRefreshToken(refreshToken);
}
tokenStore.removeAccessToken(existingAccessToken);
}
else {
tokenStore.storeAccessToken(existingAccessToken, authentication);
return existingAccessToken;
}
}
//2. accessToken refreshToken
refreshToken = createRefreshToken(authentication);
OAuth2AccessToken accessToken = createAccessToken(authentication, refreshToken);
tokenStore.storeAccessToken(accessToken, authentication);
tokenStore.storeRefreshToken(refreshToken, authentication);
return accessToken;
}
/**
* aceessToken
*/
@Transactional(noRollbackFor={InvalidTokenException.class, InvalidGrantException.class})
public OAuth2AccessToken refreshAccessToken(String refreshTokenValue, TokenRequest tokenRequest)
throws AuthenticationException {
//1. token
OAuth2RefreshToken refreshToken = tokenStore.readRefreshToken(refreshTokenValue);
//2.
OAuth2Authentication authentication = tokenStore.readAuthenticationForRefreshToken(refreshToken);
//3. 、 token
refreshToken = createRefreshToken(authentication);
OAuth2AccessToken accessToken = createAccessToken(authentication, refreshToken);
tokenStore.storeAccessToken(accessToken, authentication);
tokenStore.storeRefreshToken(accessToken.getRefreshToken(), authentication);
return accessToken;
}
/**
* accessToken OAuth2Authentication
*/
public OAuth2Authentication loadAuthentication(String accessTokenValue) throws AuthenticationException,
InvalidTokenException {
OAuth2AccessToken accessToken = tokenStore.readAccessToken(accessTokenValue);
OAuth2Authentication result = tokenStore.readAuthentication(accessToken);
//
if (clientDetailsService != null) {
String clientId = result.getOAuth2Request().getClientId();
try {
clientDetailsService.loadClientByClientId(clientId);
}
catch (ClientRegistrationException e) {
throw new InvalidTokenException("Client not valid: " + clientId, e);
}
}
return result;
}
/**
* RefreshToken json
*/
private OAuth2RefreshToken createRefreshToken(OAuth2Authentication authentication) {
// OAuth2RefreshToken : @JsonValue String getValue();
return new DefaultOAuth2RefreshToken(value);
}
/**
* OAuth2AccessToken
*/
private OAuth2AccessToken createAccessToken(OAuth2Authentication authentication, OAuth2RefreshToken refreshToken) {
// AccessToken
/**OAuth2AccessToken
private String value;
private Date expiration;
private String tokenType = BEARER_TYPE.toLowerCase();
private OAuth2RefreshToken refreshToken;
private Set scope;
private Map additionalInformation = Collections.emptyMap();
*/
DefaultOAuth2AccessToken token = new DefaultOAuth2AccessToken(UUID.randomUUID().toString());
token.setRefreshToken(refreshToken);
token.setScope(authentication.getOAuth2Request().getScope());
// accessTokenEnhancer
return accessTokenEnhancer != null ? accessTokenEnhancer.enhance(token, authentication) : token;
}
}
3.자원 서버 에 접근 하여 보 호 된 자원:
accesstoken 자원 가 져 오기,요청 헤더 에 토 큰 추가,**Bearer 추가**
방문
(1)PostMan 도구:GET/POST:/xxx/xxxx 헤더:Authorization Bearer accesstoken
(2)Curl 명령:curl-X GET\\http://localhost:9001/test \ -i -H "Accept: application/json" -H "Authorization: Bearer eyJhbG" \
4.AuthorizationServerEndpoints Configurer 설정:
주로 생각 하 는 ServerBean 을 주입 한다.
/**
* token
* 1. AuthenticationManager
* 2. AccessToken tokenStore, 。
*/
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
TokenEnhancerChain tokenEnhancerChain = new TokenEnhancerChain();
endpoints
.authenticationManager(authenticationManager)
.userDetailsService(userDetailsService) //MUST: AuthenticationManager , UserDetails
.tokenStore(tokenStore)//token
.tokenEnhancer(tokenEnhancerChain);//token
}
// Endpoints ,
public final class AuthorizationServerEndpointsConfigurer {
private AuthorizationServerTokenServices tokenServices;
private ConsumerTokenServices consumerTokenServices;
private AuthorizationCodeServices authorizationCodeServices;
private ResourceServerTokenServices resourceTokenServices;
private TokenStore tokenStore;
private TokenEnhancer tokenEnhancer;
private AccessTokenConverter accessTokenConverter;
private ApprovalStore approvalStore;
private TokenGranter tokenGranter;
private OAuth2RequestFactory requestFactory;
private OAuth2RequestValidator requestValidator;
private UserApprovalHandler userApprovalHandler;
private AuthenticationManager authenticationManager;
private ClientDetailsService clientDetailsService;
private String prefix;
private Map patternMap = new HashMap();
private Set allowedTokenEndpointRequestMethods = new HashSet();
private FrameworkEndpointHandlerMapping frameworkEndpointHandlerMapping;
private boolean approvalStoreDisabled;
private List
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Is Eclipse IDE dying?In 2014 the Eclipse IDE is the leading development environment for Java with a market share of approximately 65%. but ac...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.