自己做网站开店,建设校园网站的必要性,怎样开电商,淘宝引流推广怎么做1. Oauth 定义
1.1 角色
OAuth定义了四个角色#xff1a;
资源所有者
一个能够授权访问受保护资源的实体。当资源所有者是一个人时#xff0c;它被称为最终用户。
资源服务器
托管受保护资源的服务器能够使用访问令牌接受和响应受保护的资源请求。
客户
代表资源所有…1. Oauth 定义
1.1 角色
OAuth定义了四个角色
资源所有者
一个能够授权访问受保护资源的实体。当资源所有者是一个人时它被称为最终用户。
资源服务器
托管受保护资源的服务器能够使用访问令牌接受和响应受保护的资源请求。
客户
代表资源所有者及其授权的应用程序进行受保护的资源请求。术语客户端并不意味着任何特定的实现特征例如应用程序是在服务器台式机还是其他设备上执行的。
授权服务器
服务器在成功认证资源所有者并获得授权后向客户端发放访问令牌。 1.2 协议流程
图1中所示的抽象OAuth 2.0流程描述了四个角色之间的交互并包含以下步骤
A 客户端请求资源所有者的授权。授权请求可以直接给资源所有者如图所示或者优选间接地通过授权服务器作为中介。 B 客户端接收授权许可这是一种代表资源所有者授权的凭证使用本规范中定义的四种授权类型之一或使用扩展授权类型表示。授权授予类型取决于客户端用于请求授权的方法以及授权服务器支持的类型。 C 客户端通过向授权服务器进行认证并携带授权来请求访问令牌。 D 授权服务器对客户端进行身份验证并验证授权并且如果有效则发出访问令牌。 E 客户端从资源服务器请求受保护的资源并通过携带访问令牌进行认证。 F 资源服务器验证访问令牌并且如果有效则为该请求提供服务。
客户从资源所有者步骤A和B中描述获得授权许可的首选方法是使用授权服务器作为中介 2 模式
oauth2根据使用场景不同分成了4种模式 ● 客户端模式client credentials标准的 Server 授权模式非常适合 Server 端的 Web 应用。一旦资源的拥有者授权访问他们的数据之后他们将会被重定向到 Web 应用并在 URL 的查询参数中附带一个授权码code。在客户端里该 code 用于请求访问令牌access_token。并且该令牌交换的过程是两个服务端之前完成的防止其他人甚至是资源拥有者本人得到该令牌。另外在该授权模式下可以通过 refresh_token 来刷新令牌以延长访问授权时间也是最为复杂的一种方式。 ● 密码模式resource owner password credentials 自己有一套用户体系这种模式要求用户提供用户名和密码来交换访问令牌access_token。该模式仅用于非常值得信任的用户例如API提供者本人所写的移动应用。虽然用户也要求提供密码但并不需要存储在设备上。因为初始验证之后只需将 OAuth 的令牌记录下来即可。如果用户希望取消授权因为其真实密码并没有被记录因此无需修改密码就可以立即取消授权。token本身也只是得到有限的授权因此相比最传统的 username/password 授权该模式依然更为安全。 ● 授权码模式authorization code 该模式是所有授权模式中最简单的一种并为运行于浏览器中的脚本应用做了优化。当用户访问该应用时服务端会立即生成一个新的访问令牌access_token并通过URL的#hash段传回客户端。这时客户端就可以利用JavaScript等将其取出然后请求API接口。该模式不需要授权码code当然也不会提供refresh token以获得长期访问的入口。 ● 简化模式implicit 没有用户的概念一种基于 APP 的密钥直接进行授权因此 APP 的权限非常大。它适合像数据库或存储服务器这种对 API 的访问需求。
Oauth基于客户端与认证服务器验证的能力定义了两种客户端类型以及维护客户端认证信息的能力: 客户端模式、密码模式。
基础参数定义 grant_type 发放令牌类型、 client_id (客户端标识id) username用户帐号 password 用户密码 client_secret客户端标识密钥 refresh_token 刷新令牌 scope表示权限范围可选项 Oauth2 Client 集成
pom.xml
dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-web/artifactId/dependency
dependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-starter-security/artifactId
/dependency
dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-oauth2-client/artifactId
/dependencypackage com.lvyuanj.upms.oauthclient.config;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.oauth2.client.InMemoryOAuth2AuthorizedClientService;
import org.springframework.security.oauth2.client.OAuth2AuthorizedClientService;
import org.springframework.security.oauth2.client.registration.ClientRegistration;
import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository;
import org.springframework.security.oauth2.client.registration.InMemoryClientRegistrationRepository;
import org.springframework.security.oauth2.client.web.AuthenticatedPrincipalOAuth2AuthorizedClientRepository;
import org.springframework.security.oauth2.client.web.OAuth2AuthorizedClientRepository;
import org.springframework.security.oauth2.core.AuthorizationGrantType;
import org.springframework.security.oauth2.core.ClientAuthenticationMethod;Configuration
public class UpmsOauth2LoginConfig {EnableWebSecuritypublic static class OAuth2LoginSecurityConfig extends WebSecurityConfigurerAdapter {Autowiredprivate UpmsLogoutHandler upmsLogoutHandler;Overrideprotected void configure(HttpSecurity http) throws Exception {http.authorizeRequests().anyRequest().authenticated().and().logout().addLogoutHandler(upmsLogoutHandler).and().oauth2Login();}Overridepublic void configure(WebSecurity web) throws Exception {web.ignoring().mvcMatchers(/js/**,/css/**);}}Beanpublic OAuth2AuthorizedClientService authorizedClientService(ClientRegistrationRepository clientRegistrationRepository) {return new InMemoryOAuth2AuthorizedClientService(clientRegistrationRepository);}Beanpublic OAuth2AuthorizedClientRepository authorizedClientRepository(OAuth2AuthorizedClientService authorizedClientService) {return new AuthenticatedPrincipalOAuth2AuthorizedClientRepository(authorizedClientService);}Beanpublic ClientRegistrationRepository clientRegistrationRepository() {return new InMemoryClientRegistrationRepository(this.upmsOauth2ClientRegistration());}BeanConfigurationProperties(prefix spring.security.oauth2.client.registration.upms)public UpmsClientRegistration upmsClientRegistration(){return new UpmsClientRegistration();}BeanConfigurationProperties(prefix spring.security.oauth2.client.provider.upms)public UpmsClientProvider upmsClientProvider(){return new UpmsClientProvider();}private ClientRegistration upmsOauth2ClientRegistration() {return ClientRegistration.withRegistrationId(this.upmsClientRegistration().getProvider()).clientId(this.upmsClientRegistration().getClientId()).clientSecret(this.upmsClientRegistration().getClientSecret()).clientAuthenticationMethod(ClientAuthenticationMethod.BASIC).authorizationGrantType(new AuthorizationGrantType(this.upmsClientRegistration().getAuthorizationGrantType())).redirectUriTemplate(this.upmsClientRegistration().getRedirectUriTemplate()).scope(this.upmsClientRegistration().getScope()).authorizationUri(this.upmsClientProvider().getAuthorizationUri()).tokenUri(this.upmsClientProvider().getTokenUri()).userInfoUri(this.upmsClientProvider().getUserInfoUri()).userNameAttributeName(this.upmsClientProvider().getUserNameAttribute()).clientName(this.upmsClientRegistration().getClientName()).build();}
}oauth registration config
package com.lvyuanj.upms.oauthclient.config;import lombok.Data;Data
public class UpmsClientProvider {private String authorizationUri;private String tokenUri;private String userInfoUri;private String userNameAttribute;
}package com.lvyuanj.upms.oauthclient.config;import lombok.Data;Data
public class UpmsClientRegistration {private String provider;private String clientId;private String clientSecret;private String clientName;private String authorizationGrantType;private String redirectUriTemplate;private String scope;}退出登陆配置
package com.lvyuanj.upms.oauthclient.config;import com.lvyuanj.utils.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.logout.LogoutHandler;
import org.springframework.stereotype.Service;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;Slf4j
Service
public class UpmsLogoutHandler implements LogoutHandler {Value(${com.lvyuanj.upms.client.upms.logout-uri})private String logoutUrl;Overridepublic void logout(HttpServletRequest request, HttpServletResponse response, Authentication authentication) {try {String access_token (String) request.getSession().getAttribute(access_token);String params ;if(StringUtils.isNotBlank(access_token)){params ?access_tokenaccess_token;}response.sendRedirect(logoutUrlparams);} catch (IOException e) {e.printStackTrace();}}
}登陆成功跳转到index
package com.lvyuanj.upms.oauthclient.controller;import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.security.oauth2.client.OAuth2AuthorizedClient;
import org.springframework.security.oauth2.client.OAuth2AuthorizedClientService;
import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken;
import org.springframework.security.oauth2.core.OAuth2AccessToken;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.reactive.function.client.ClientRequest;
import org.springframework.web.reactive.function.client.ExchangeFilterFunction;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Mono;import javax.servlet.http.HttpServletRequest;
import java.util.Collections;
import java.util.Map;Slf4j
Controller
public class OAuth2Controller {Autowiredprivate OAuth2AuthorizedClientService authorizedClientService;RequestMapping(/)public String index(Model model, OAuth2AuthenticationToken authentication, HttpServletRequest request) {log.debug(authentication: JSONObject.toJSONString(authentication));OAuth2AuthorizedClient authorizedClient this.getAuthorizedClient(authentication);if(null ! authorizedClient){String access_token authorizedClient.getAccessToken().getTokenValue();log.debug(access_token: access_token);request.getSession().setAttribute(access_token, access_token);model.addAttribute(userName, authentication.getName());model.addAttribute(clientName, authorizedClient.getClientRegistration().getClientName());return index;}else {return logout;}}private OAuth2AuthorizedClient getAuthorizedClient(OAuth2AuthenticationToken authentication) {return this.authorizedClientService.loadAuthorizedClient(authentication.getAuthorizedClientRegistrationId(), authentication.getName());}RequestMapping(/userinfo)public String userinfo(Model model,OAuth2AuthenticationToken authentication) {// authentication.getAuthorizedClientRegistrationId() returns the// registrationId of the Client that was authorized during the Login flowOAuth2AuthorizedClient authorizedClient this.authorizedClientService.loadAuthorizedClient(authentication.getAuthorizedClientRegistrationId(),authentication.getName());OAuth2AccessToken accessToken authorizedClient.getAccessToken();System.out.println(accessToken.getTokenValue());Map userAttributes Collections.emptyMap();String userInfoEndpointUri authorizedClient.getClientRegistration().getProviderDetails().getUserInfoEndpoint().getUri();if (!StringUtils.isEmpty(userInfoEndpointUri)) {// userInfoEndpointUri is optional for OIDC ClientsuserAttributes WebClient.builder().filter(oauth2Credentials(authorizedClient)).build().get().uri(userInfoEndpointUri).retrieve().bodyToMono(Map.class).block();}model.addAttribute(userAttributes, userAttributes);return userinfo;}private ExchangeFilterFunction oauth2Credentials(OAuth2AuthorizedClient authorizedClient) {return ExchangeFilterFunction.ofRequestProcessor(clientRequest - {ClientRequest authorizedRequest ClientRequest.from(clientRequest).header(HttpHeaders.AUTHORIZATION, Bearer authorizedClient.getAccessToken().getTokenValue()).build();return Mono.just(authorizedRequest);});}
}Spring Security Oauth2 Client 非常重要的过滤器OAuth2LoginAuthenticationFilter
org.springframework.security.oauth2.client.web.OAuth2LoginAuthenticationFilter#attemptAuthentication方法 public static final String DEFAULT_FILTER_PROCESSES_URI /login/oauth2/code/*; --在oauth2登陆成功之后此过滤器拦截回调接口地址Overridepublic Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response)throws AuthenticationException, IOException, ServletException {MultiValueMapString, String params OAuth2AuthorizationResponseUtils.toMultiMap(request.getParameterMap());if (!OAuth2AuthorizationResponseUtils.isAuthorizationResponse(params)) { // 判断回调数据是否有CODE 或者 STATE 参数OAuth2Error oauth2Error new OAuth2Error(OAuth2ErrorCodes.INVALID_REQUEST);throw new OAuth2AuthenticationException(oauth2Error, oauth2Error.toString());}OAuth2AuthorizationRequest authorizationRequest this.authorizationRequestRepository.removeAuthorizationRequest(request, response);if (authorizationRequest null) {OAuth2Error oauth2Error new OAuth2Error(AUTHORIZATION_REQUEST_NOT_FOUND_ERROR_CODE);throw new OAuth2AuthenticationException(oauth2Error, oauth2Error.toString());}String registrationId (String) authorizationRequest.getAdditionalParameters().get(OAuth2ParameterNames.REGISTRATION_ID);ClientRegistration clientRegistration this.clientRegistrationRepository.findByRegistrationId(registrationId);if (clientRegistration null) {OAuth2Error oauth2Error new OAuth2Error(CLIENT_REGISTRATION_NOT_FOUND_ERROR_CODE,Client Registration not found with Id: registrationId, null);throw new OAuth2AuthenticationException(oauth2Error, oauth2Error.toString());}String redirectUri UriComponentsBuilder.fromHttpUrl(UrlUtils.buildFullRequestUrl(request)).replaceQuery(null).build().toUriString();OAuth2AuthorizationResponse authorizationResponse OAuth2AuthorizationResponseUtils.convert(params, redirectUri);OAuth2LoginAuthenticationToken authenticationRequest new OAuth2LoginAuthenticationToken(clientRegistration, new OAuth2AuthorizationExchange(authorizationRequest, authorizationResponse));authenticationRequest.setDetails(this.authenticationDetailsSource.buildDetails(request));OAuth2LoginAuthenticationToken authenticationResult (OAuth2LoginAuthenticationToken) this.getAuthenticationManager().authenticate(authenticationRequest);OAuth2AuthenticationToken oauth2Authentication new OAuth2AuthenticationToken(authenticationResult.getPrincipal(),authenticationResult.getAuthorities(),authenticationResult.getClientRegistration().getRegistrationId());OAuth2AuthorizedClient authorizedClient new OAuth2AuthorizedClient(authenticationResult.getClientRegistration(),oauth2Authentication.getName(),authenticationResult.getAccessToken(),authenticationResult.getRefreshToken());this.authorizedClientRepository.saveAuthorizedClient(authorizedClient, oauth2Authentication, request, response);return oauth2Authentication;}