对spring security oauth2 的客户端模式的研究。
首要要下载spring security oauth2的源码,源码中有官方的例子,sparklr2 和tonr2。sparklr2模拟授权服务器和资源服务器,tonr2模拟客户端。
在tonr2的index.jsp中加了一行代码:
<li><a href="${base}trusted/message">trusted message</a></li>
然后打开http://localhost/tonr2/ 就可以点击trusted message这个链接,然后就是触发了oauth2的客户端模式的例子。
1.通过mvc的映射先触发了tonr2的SparklrController类的trusted函数。
2.tonr2的WebMvcConfig中已经初始化了SparklrServiceImpl。
3.trusted函数调用SparklrServiceImpl的getTrustedMessage()函数。
4.getTrustedMessage函数中调用trustedClientRestTemplate.getForObject(URI.create(sparklrTrustedMessageURL), String.class);
5.sparklrTrustedMessageURL同样是通过WebMvcConfig中@Value("${sparklrTrustedMessageURL}") String sparklrTrustedMessageURL,来初始化的。
6.trustedClientRestTemplate同样是通过WebMvcConfig中 @Qualifier("trustedClientRestTemplate") RestOperations trustedClientRestTemplate,来初始化的。
7.trustedClientRestTemplate是通过下面代码初始化的,实际上就是个OAuth2RestTemplate对象。
public OAuth2RestTemplate trustedClientRestTemplate() { return new OAuth2RestTemplate(trusted(), new DefaultOAuth2ClientContext()); }8.trustedClientRestTemplate.getForObject 也就是OAuth2RestTemplate.getForObject 这个方法写在他的父类里。
public <T> T getForObject(String url, Class<T> responseType, Object... urlVariables) throws RestClientException { RequestCallback requestCallback = acceptHeaderRequestCallback(responseType); HttpMessageConverterExtractor<T> responseExtractor = new HttpMessageConverterExtractor<T>(responseType, getMessageConverters(), logger); return execute(url, HttpMethod.GET, requestCallback, responseExtractor, urlVariables); }9.getForObject 里调用了acceptHeaderRequestCallback,acceptHeaderRequestCallback里调用了AcceptHeaderRequestCallback.
@Override protected ClientHttpRequest createRequest(URI uri, HttpMethod method) throws IOException { OAuth2AccessToken accessToken = getAccessToken(); AuthenticationScheme authenticationScheme = resource.getAuthenticationScheme(); if (AuthenticationScheme.query.equals(authenticationScheme) || AuthenticationScheme.form.equals(authenticationScheme)) { uri = appendQueryParameter(uri, accessToken); } ClientHttpRequest req = super.createRequest(uri, method); if (AuthenticationScheme.header.equals(authenticationScheme)) { authenticator.authenticate(resource, getOAuth2ClientContext(), req); } return req; }
public OAuth2AccessToken obtainAccessToken(OAuth2ProtectedResourceDetails resource, AccessTokenRequest request) throws UserRedirectRequiredException, AccessDeniedException { OAuth2AccessToken accessToken = null; OAuth2AccessToken existingToken = null; Authentication auth = SecurityContextHolder.getContext().getAuthentication(); if (auth instanceof AnonymousAuthenticationToken) { if (!resource.isClientOnly()) { throw new InsufficientAuthenticationException( "Authentication is required to obtain an access token (anonymous not allowed)"); } } if (resource.isClientOnly() || (auth != null && auth.isAuthenticated())) { existingToken = request.getExistingToken(); if (existingToken == null && clientTokenServices != null) { existingToken = clientTokenServices.getAccessToken(resource, auth); } if (existingToken != null) { if (existingToken.isExpired()) { if (clientTokenServices != null) { clientTokenServices.removeAccessToken(resource, auth); } OAuth2RefreshToken refreshToken = existingToken.getRefreshToken(); if (refreshToken != null) { accessToken = refreshAccessToken(resource, refreshToken, request); } } else { accessToken = existingToken; } } } // Give unauthenticated users a chance to get a token and be redirected if (accessToken == null) { // looks like we need to try to obtain a new token. accessToken = obtainNewAccessTokenInternal(resource, request); if (accessToken == null) { throw new IllegalStateException("An OAuth 2 access token must be obtained or an exception thrown."); } } if (clientTokenServices != null && (resource.isClientOnly() || auth != null && auth.isAuthenticated())) { clientTokenServices.saveAccessToken(resource, auth, accessToken); } return accessToken; }
for (AccessTokenProvider tokenProvider : chain) { if (tokenProvider.supportsResource(details)) { return tokenProvider.obtainAccessToken(details, request); } }
return getRestTemplate().execute(getAccessTokenUri(resource, form), getHttpMethod(), getRequestCallback(resource, form, headers), extractor , form.toSingleValueMap());
tonr2 10:10:12.997 [DEBUG] ClientCredentialsAccessTokenProvider - Retrieving token from http://localhost:80/sparklr2/oauth/token tonr2 10:10:13.027 [DEBUG] RestTemplate - Created POST request for "http://localhost:80/sparklr2/oauth/token" tonr2 10:10:13.028 [DEBUG] ClientCredentialsAccessTokenProvider - Encoding and sending form: {grant_type=[client_credentials], scope=[trust]} sparklr23 10:10:13.050 [DEBUG] AntPathRequestMatcher - Checking match of request : '/oauth/token'; against '/webjars/**' sparklr23 10:10:13.050 [DEBUG] AntPathRequestMatcher - Checking match of request : '/oauth/token'; against '/images/**' sparklr23 10:10:13.050 [DEBUG] AntPathRequestMatcher - Checking match of request : '/oauth/token'; against '/oauth/uncache_approvals' sparklr23 10:10:13.050 [DEBUG] AntPathRequestMatcher - Checking match of request : '/oauth/token'; against '/oauth/cache_approvals' sparklr23 10:10:13.050 [DEBUG] OrRequestMatcher - Trying to match using Ant [pattern='/oauth/token'] sparklr23 10:10:13.050 [DEBUG] AntPathRequestMatcher - Checking match of request : '/oauth/token'; against '/oauth/token' sparklr23 10:10:13.050 [DEBUG] OrRequestMatcher - matched sparklr23 10:10:13.052 [DEBUG] FilterChainProxy - /oauth/token at position 1 of 11 in additional filter chain; firing Filter: 'WebAsyncManagerIntegrationFilter' sparklr23 10:10:13.058 [DEBUG] FilterChainProxy - /oauth/token at position 2 of 11 in additional filter chain; firing Filter: 'SecurityContextPersistenceFilter' sparklr23 10:10:13.059 [DEBUG] FilterChainProxy - /oauth/token at position 3 of 11 in additional filter chain; firing Filter: 'HeaderWriterFilter' sparklr23 10:10:13.059 [DEBUG] HstsHeaderWriter - Not injecting HSTS header since it did not match the requestMatcher org.springframework.security.web.header.writers.HstsHeaderWriter$SecureRequestMatcher@bb64568 sparklr23 10:10:13.059 [DEBUG] FilterChainProxy - /oauth/token at position 4 of 11 in additional filter chain; firing Filter: 'LogoutFilter' sparklr23 10:10:13.059 [DEBUG] AntPathRequestMatcher - Checking match of request : '/oauth/token'; against '/logout' sparklr23 10:10:13.059 [DEBUG] FilterChainProxy - /oauth/token at position 5 of 11 in additional filter chain; firing Filter: 'BasicAuthenticationFilter' sparklr23 10:10:13.063 [DEBUG] BasicAuthenticationFilter - Basic Authentication Authorization header found for user 'my-client-with-registered-redirect' sparklr23 10:10:13.064 [DEBUG] ProviderManager - Authentication attempt using org.springframework.security.authentication.dao.DaoAuthenticationProvider sparklr23 10:10:13.083 [DEBUG] BasicAuthenticationFilter - Authentication success: org.springframework.security.authentication.UsernamePasswordAuthenticationToken@f3bb37ef: Principal: org.springframework.security.core.userdetails.User@3c4746e1: Username: my-client-with-registered-redirect; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Granted Authorities: ROLE_CLIENT; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@957e: RemoteIpAddress: 127.0.0.1; SessionId: null; Granted Authorities: ROLE_CLIENT sparklr23 10:10:13.083 [DEBUG] FilterChainProxy - /oauth/token at position 6 of 11 in additional filter chain; firing Filter: 'RequestCacheAwareFilter' sparklr23 10:10:13.084 [DEBUG] FilterChainProxy - /oauth/token at position 7 of 11 in additional filter chain; firing Filter: 'SecurityContextHolderAwareRequestFilter' sparklr23 10:10:13.086 [DEBUG] FilterChainProxy - /oauth/token at position 8 of 11 in additional filter chain; firing Filter: 'AnonymousAuthenticationFilter' sparklr23 10:10:13.086 [DEBUG] AnonymousAuthenticationFilter - SecurityContextHolder not populated with anonymous token, as it already contained: 'org.springframework.security.authentication.UsernamePasswordAuthenticationToken@f3bb37ef: Principal: org.springframework.security.core.userdetails.User@3c4746e1: Username: my-client-with-registered-redirect; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Granted Authorities: ROLE_CLIENT; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@957e: RemoteIpAddress: 127.0.0.1; SessionId: null; Granted Authorities: ROLE_CLIENT' sparklr23 10:10:13.086 [DEBUG] FilterChainProxy - /oauth/token at position 9 of 11 in additional filter chain; firing Filter: 'SessionManagementFilter' sparklr23 10:10:13.086 [DEBUG] CompositeSessionAuthenticationStrategy - Delegating to org.springframework.security.web.authentication.session.ChangeSessionIdAuthenticationStrategy@135de411 sparklr23 10:10:13.086 [DEBUG] FilterChainProxy - /oauth/token at position 10 of 11 in additional filter chain; firing Filter: 'ExceptionTranslationFilter' sparklr23 10:10:13.086 [DEBUG] FilterChainProxy - /oauth/token at position 11 of 11 in additional filter chain; firing Filter: 'FilterSecurityInterceptor' sparklr23 10:10:13.087 [DEBUG] AntPathRequestMatcher - Checking match of request : '/oauth/token'; against '/oauth/token' sparklr23 10:10:13.088 [DEBUG] FilterSecurityInterceptor - Secure object: FilterInvocation: URL: /oauth/token; Attributes: [fullyAuthenticated] sparklr23 10:10:13.088 [DEBUG] FilterSecurityInterceptor - Previously Authenticated: org.springframework.security.authentication.UsernamePasswordAuthenticationToken@f3bb37ef: Principal: org.springframework.security.core.userdetails.User@3c4746e1: Username: my-client-with-registered-redirect; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Granted Authorities: ROLE_CLIENT; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@957e: RemoteIpAddress: 127.0.0.1; SessionId: null; Granted Authorities: ROLE_CLIENT sparklr23 10:10:13.096 [DEBUG] AffirmativeBased - Voter: org.springframework.security.web.access.expression.WebExpressionVoter@51e2ee04, returned: 1 sparklr23 10:10:13.096 [DEBUG] FilterSecurityInterceptor - Authorization successful sparklr23 10:10:13.096 [DEBUG] FilterSecurityInterceptor - RunAsManager did not change Authentication object sparklr23 10:10:13.097 [DEBUG] FilterChainProxy - /oauth/token reached end of additional filter chain; proceeding with original chain sparklr23 10:10:13.108 [DEBUG] FrameworkEndpointHandlerMapping - Looking up handler method for path /oauth/token sparklr23 10:10:13.111 [DEBUG] FrameworkEndpointHandlerMapping - Returning handler method [public org.springframework.http.ResponseEntity<org.springframework.security.oauth2.common.OAuth2AccessToken> org.springframework.security.oauth2.provider.endpoint.TokenEndpoint.getAccessToken(java.security.Principal,java.util.Map<java.lang.String, java.lang.String>)] sparklr23 10:10:13.131 [DEBUG] ClientCredentialsTokenGranter - Getting access token for: my-client-with-registered-redirect sparklr23 10:10:13.219 [DEBUG] ExceptionTranslationFilter - Chain processed normally sparklr23 10:10:13.219 [DEBUG] SecurityContextPersistenceFilter - SecurityContextHolder now cleared, as request processing completed tonr2 10:10:13.227 [DEBUG] RestTemplate - POST request for "http://localhost:80/sparklr2/oauth/token" resulted in 200 (OK) tonr2 10:10:13.415 [DEBUG] HttpMessageConverterExtractor - Reading [interface org.springframework.security.oauth2.common.OAuth2AccessToken] as "application/json;charset=UTF-8" using [org.springframework.http.converter.json.MappingJackson2HttpMessageConverter@4c825fa3]1.第一次请求被BasicAuthenticationFilter拦截,具体内容如下:
String[] tokens = extractAndDecodeHeader(header, request);先将request的header中Authorization参数拿出来。Authorization = Basic xxxxxxxxxxxxxxxxxxxxxxx;格式得,xxxxxxxxxxx是经过base64编码的。上句代码主要是将xxxxxxxxxxx解码。解码出来的内容应该是my-client-with-registered-redirect:nnnnnnnnn;其中my-client-with-registered-redirect是客户端id,是在你客户端配置的时候你自己设置进去的,同样在认证端也要配置,否则系统将认证失败。nnnnnnnnn是token。
public Authentication authenticate(Authentication authentication) throws AuthenticationException { Assert.isInstanceOf(UsernamePasswordAuthenticationToken.class, authentication, messages.getMessage("AbstractUserDetailsAuthenticationProvider.onlySupports", "Only UsernamePasswordAuthenticationToken is supported")); // Determine username String username = (authentication.getPrincipal() == null) ? "NONE_PROVIDED" : authentication.getName(); boolean cacheWasUsed = true; UserDetails user = this.userCache.getUserFromCache(username); if (user == null) { cacheWasUsed = false; try { user = retrieveUser(username, (UsernamePasswordAuthenticationToken) authentication); } catch (UsernameNotFoundException notFound) { logger.debug("User '" + username + "' not found"); if (hideUserNotFoundExceptions) { throw new BadCredentialsException(messages.getMessage( "AbstractUserDetailsAuthenticationProvider.badCredentials", "Bad credentials")); } else { throw notFound; } } Assert.notNull(user, "retrieveUser returned null - a violation of the interface contract"); } try { preAuthenticationChecks.check(user); additionalAuthenticationChecks(user, (UsernamePasswordAuthenticationToken) authentication); } catch (AuthenticationException exception) { if (cacheWasUsed) { // There was a problem, so try again after checking // we're using latest data (i.e. not from the cache) cacheWasUsed = false; user = retrieveUser(username, (UsernamePasswordAuthenticationToken) authentication); preAuthenticationChecks.check(user); additionalAuthenticationChecks(user, (UsernamePasswordAuthenticationToken) authentication); } else { throw exception; } } postAuthenticationChecks.check(user); if (!cacheWasUsed) { this.userCache.putUserInCache(user); } Object principalToReturn = user; if (forcePrincipalAsString) { principalToReturn = user.getUsername(); } return createSuccessAuthentication(principalToReturn, authentication, user); }
public void init(HttpSecurity http) throws Exception { registerDefaultAuthenticationEntryPoint(http); if (passwordEncoder != null) { http.getSharedObject(AuthenticationManagerBuilder.class) .userDetailsService(new ClientDetailsUserDetailsService(clientDetailsService())) .passwordEncoder(passwordEncoder()); } else { http.userDetailsService(new ClientDetailsUserDetailsService(clientDetailsService())); } http.securityContext().securityContextRepository(new NullSecurityContextRepository()).and().csrf().disable() .httpBasic().realmName(realm); }
public InMemoryClientDetailsServiceBuilder inMemory() throws Exception { InMemoryClientDetailsServiceBuilder next = getBuilder().inMemory(); setBuilder(next); return next; }
clients.inMemory().withClient("tonr") .resourceIds(SPARKLR_RESOURCE_ID) .authorizedGrantTypes("authorization_code", "implicit") .authorities("ROLE_CLIENT") .scopes("read", "write") .secret("secret") .and() .withClient("tonr-with-redirect") .resourceIds(SPARKLR_RESOURCE_ID) .authorizedGrantTypes("authorization_code", "implicit") .authorities("ROLE_CLIENT") .scopes("read", "write") .secret("secret") .redirectUris(tonrRedirectUri) .and() .withClient("my-client-with-registered-redirect") .resourceIds(SPARKLR_RESOURCE_ID) .authorizedGrantTypes("authorization_code", "client_credentials") .authorities("ROLE_CLIENT") .scopes("read", "trust") .redirectUris("http://anywhere?key=value")2.第一次请求,被FilterSecurityInterceptor拦截,具体内容如下:
相关推荐
为了写oauth2,从官网下载的实例sparklr2与tonr2,但是官网实例是maven的,不能直接用Eclipse运行,好一顿操作之后,浪费了一些时间才改为可运行的Eclipse项目,供大家参考
从官网下载的oauth2实例sparklr2与tonr2
主要介绍了Spring Security OAuth2集成短信验证码登录以及第三方登录,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
Spring Security OAuth2.0学习笔记 什么是认证、授权、会话。 ... 基于session认证机制的运作流程。...Spring cloud Security OAuth2包括哪些组件?职责? 分布式系统认证需要解决的问题? 掌握学习方法,掌握思考方式。
赠送jar包:spring-security-oauth2-2.3.5.RELEASE.jar; 赠送原API文档:spring-security-oauth2-2.3.5.RELEASE-javadoc.jar; 赠送源代码:spring-security-oauth2-2.3.5.RELEASE-sources.jar; 赠送Maven依赖信息...
spring security oauth2的client演示包tonr2,所有的jar都齐全了
#OAuth2-Defender ##主要技术 Maven Spring Boot Spring Security Spring Security OAuth2.0 MySQL ##修改数据库配置 修改defender-oauth2-authorization\src\main\resources\...
spring security oauth2的源码,方便研究,备份一下。
主要介绍了Spring Security OAuth2认证授权示例详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
Spring boot+Spring Security Oauth2.0,Sprint cloud+Spring Security Oauth2集成。四种认证方式。附带有代码,和案例,案例,还有视频链接。我保证看完就回,如果视频链接失效,评论回复我,我单独再给你一份。
该资源是springsecurity+oauth2+jwt实现的单点登录demo,模式为授权码模式,实现自定义登录页面和自定义授权页面。应用数据存在内存中或者存在数据库中(附带数据库表结构),token存储分为数据库或者Redis。demo...
项目中使用到的技术包含SpringBoot、SpringSecurity&oauth2(安全资源和授权中心模式、包括登录接口自定义返回字段、自定义手机号+密码登录、自定义免密登录)、Queue队列、线程池、xss攻击配置、SpringCache、Mybatis...
spring security oauth2.0 需要的基础 sql 文件
spring-boot spring-security-oauth2 完整demo,可以使用微信的方式来获取token和查看资源,注意看代码中的备注
spring security 整合oauth2,进行权限授权管理,例子简单好用。
spring-security-oauth2下的sparklr2的war包,官方的没有现成的war包,需要使用maven打包,这个是打包好的
spring security 基于oauth 2.0 实现 sso 单点登录Demo 使用 spring security 基于oauth 2.0 实现 sso 单点登录Demo spring boot + spring security + spring security oauth
Springboot整合Spring security+Oauth2+JWT搭建认证服务器,网关,微服务之间权限认证及授权
Spring Security Oauth2 password登录及token续约,使用数据库及redis存储token
视频配套笔记_Spring Security OAuth2.0认证授权_v1.1 完整详细 pdf无障碍阅读,代码完整可复制