赞
踩
主要配置
security:
oauth2:
resource:
# oauth2 Server
user-info-uri: http://localhost/user/info
import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.security.oauth2.client.EnableOAuth2Sso; /** * 资源服务器 */ @EnableOAuth2Sso @SpringBootApplication public class OAuth2Resource { public static void main(String[] args) { SpringApplication application = new SpringApplication(OAuth2Resource.class); application.run(args); } }
import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.http.SessionCreationPolicy; import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer; import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter; /** * 资源服务权限 * * @author lihy */ @Configuration @EnableResourceServer @EnableGlobalMethodSecurity(prePostEnabled = true) public class ResourceServerConfiguration extends ResourceServerConfigurerAdapter { @Override public void configure(HttpSecurity http) throws Exception { http .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED) .and() .requestMatchers().anyRequest() .and() .cors() .and() .anonymous() .and() .authorizeRequests() .antMatchers("/client/details/**") .access("#oauth2.hasAnyScope('read','write')") .antMatchers("/order/**").authenticated(); } }
import com.dcssn.core.result.HttpResult; import com.dcssn.core.result.HttpResultUtil; import org.springframework.security.oauth2.provider.OAuth2Authentication; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import java.util.LinkedHashMap; @RestController public class UserController { @RequestMapping("/user/info") public HttpResult user(OAuth2Authentication principal) { LinkedHashMap<String, Object> principalMap = (LinkedHashMap<String, Object>) principal.getUserAuthentication().getDetails(); return HttpResultUtil.success(principalMap.get("principal")); } }
import com.dcssn.core.result.HttpResult; import com.dcssn.core.result.HttpResultUtil; import com.dcssn.oauth2.repository.entity.OauthClientDetails; import com.dcssn.oauth2.repository.repository.OauthClientDetailsRepository; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import java.util.List; /** * 应用编辑 * * @author lihy */ @RequestMapping("/client/details") @RestController public class ClientDetailsController { private final OauthClientDetailsRepository repository; public ClientDetailsController(OauthClientDetailsRepository repository) { this.repository = repository; } /** * @return */ @RequestMapping("/list") public HttpResult list() { List<OauthClientDetails> all = repository.findAll(); return HttpResultUtil.success(all); } }
以上就是项目全部的代码了
请求 /user/info 接口是有正常返回的
请求 /client/details/list 返回 Status Code: 403
response
{"error":"insufficient_scope","error_description":"Insufficient scope for this resource","scope":"read"}
在此项目OAuth2Server /user/info 中加断点
principal为
在此项目OAuth2Resource /user/info 中加断点
principal为
发现在OAuth2Resource 项目中信息丢失了,那就看看在哪丢的再找回来吧
org.springframework.boot.autoconfigure.security.oauth2.resource.UserInfoTokenServices#extractAuthentication
private OAuth2Authentication extractAuthentication(Map<String, Object> map) {
Object principal = this.getPrincipal(map);
List<GrantedAuthority> authorities = this.authoritiesExtractor.extractAuthorities(map);
OAuth2Request request = new OAuth2Request((Map)null, this.clientId, (Collection)null, true, (Set)null, (Set)null, (String)null, (Set)null, (Map)null);
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(principal, "N/A", authorities);
token.setDetails(map);
return new OAuth2Authentication(request, token);
}
new OAuth2Request 传入的参数都是null 重新实现这部分代码就好了
import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.boot.autoconfigure.security.oauth2.resource.AuthoritiesExtractor; import org.springframework.boot.autoconfigure.security.oauth2.resource.FixedAuthoritiesExtractor; import org.springframework.boot.autoconfigure.security.oauth2.resource.FixedPrincipalExtractor; import org.springframework.boot.autoconfigure.security.oauth2.resource.PrincipalExtractor; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.AuthenticationException; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.oauth2.client.OAuth2RestOperations; import org.springframework.security.oauth2.client.OAuth2RestTemplate; import org.springframework.security.oauth2.client.resource.BaseOAuth2ProtectedResourceDetails; import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken; import org.springframework.security.oauth2.common.OAuth2AccessToken; import org.springframework.security.oauth2.common.exceptions.InvalidTokenException; import org.springframework.security.oauth2.provider.OAuth2Authentication; import org.springframework.security.oauth2.provider.OAuth2Request; import org.springframework.security.oauth2.provider.token.ResourceServerTokenServices; import org.springframework.util.Assert; import java.io.Serializable; import java.util.*; import java.util.stream.Collectors; /** * {@link ResourceServerTokenServices} that uses a user info REST service. * * @author Dave Syer * @since 1.3.0 */ public class MyUserInfoTokenServices implements ResourceServerTokenServices { protected final Log logger = LogFactory.getLog(getClass()); private final String userInfoEndpointUrl; private final String clientId; private OAuth2RestOperations restTemplate; private String tokenType = DefaultOAuth2AccessToken.BEARER_TYPE; private AuthoritiesExtractor authoritiesExtractor = new FixedAuthoritiesExtractor(); private PrincipalExtractor principalExtractor = new FixedPrincipalExtractor(); public MyUserInfoTokenServices(String userInfoEndpointUrl, String clientId) { this.userInfoEndpointUrl = userInfoEndpointUrl; this.clientId = clientId; } public void setTokenType(String tokenType) { this.tokenType = tokenType; } public void setRestTemplate(OAuth2RestOperations restTemplate) { this.restTemplate = restTemplate; } public void setAuthoritiesExtractor(AuthoritiesExtractor authoritiesExtractor) { Assert.notNull(authoritiesExtractor, "AuthoritiesExtractor must not be null"); this.authoritiesExtractor = authoritiesExtractor; } public void setPrincipalExtractor(PrincipalExtractor principalExtractor) { Assert.notNull(principalExtractor, "PrincipalExtractor must not be null"); this.principalExtractor = principalExtractor; } @Override public OAuth2Authentication loadAuthentication(String accessToken) throws AuthenticationException, InvalidTokenException { Map<String, Object> map = getMap(this.userInfoEndpointUrl, accessToken); if (map.containsKey("error")) { if (this.logger.isDebugEnabled()) { this.logger.debug("userinfo returned error: " + map.get("error")); } throw new InvalidTokenException(accessToken); } return extractAuthentication(map); } private OAuth2Authentication extractAuthentication(Map<String, Object> map) { Object principal = getPrincipal(map); List<GrantedAuthority> authorities = this.authoritiesExtractor.extractAuthorities(map); LinkedHashMap<String, Object> oauth2Request = (LinkedHashMap<String, Object>) map.get("oauth2Request"); OAuth2Request request = buildOAuth2Request(oauth2Request); UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken( principal, "N/A", authorities); token.setDetails(map); return new OAuth2Authentication(request, token); } private OAuth2Request buildOAuth2Request(LinkedHashMap<String, Object> oauth2Request) { Map<String, String> requestParameters = (Map<String, String>) oauth2Request.get("requestParameters"); String clientId = (String) oauth2Request.get("clientId"); List<GrantedAuthority> authorities = this.authoritiesExtractor.extractAuthorities(oauth2Request); boolean approved = (boolean) oauth2Request.get("approved"); Set<String> scope = ((List<String>) oauth2Request.get("scope")).stream().collect(Collectors.toSet()); Set<String> resourceIds = ((List<String>) oauth2Request.get("resourceIds")).stream().collect(Collectors.toSet()); String redirectUri= (String) oauth2Request.get("redirectUri"); Set<String> responseTypes = ((List<String>) oauth2Request.get("responseTypes")).stream().collect(Collectors.toSet()); Map<String, Serializable> extensionProperties= (Map<String, Serializable>) oauth2Request.get("extensions"); OAuth2Request request = new OAuth2Request(requestParameters, clientId, authorities, approved, scope, resourceIds, redirectUri, responseTypes, extensionProperties); return request; } /** * Return the principal that should be used for the token. The default implementation * delegates to the {@link PrincipalExtractor}. * * @param map the source map * @return the principal or {@literal "unknown"} */ protected Object getPrincipal(Map<String, Object> map) { Object principal = this.principalExtractor.extractPrincipal(map); return (principal == null ? "unknown" : principal); } @Override public OAuth2AccessToken readAccessToken(String accessToken) { throw new UnsupportedOperationException("Not supported: read access token"); } @SuppressWarnings({"unchecked"}) private Map<String, Object> getMap(String path, String accessToken) { if (this.logger.isDebugEnabled()) { this.logger.debug("Getting user info from: " + path); } try { OAuth2RestOperations restTemplate = this.restTemplate; if (restTemplate == null) { BaseOAuth2ProtectedResourceDetails resource = new BaseOAuth2ProtectedResourceDetails(); resource.setClientId(this.clientId); restTemplate = new OAuth2RestTemplate(resource); } OAuth2AccessToken existingToken = restTemplate.getOAuth2ClientContext() .getAccessToken(); if (existingToken == null || !accessToken.equals(existingToken.getValue())) { DefaultOAuth2AccessToken token = new DefaultOAuth2AccessToken( accessToken); token.setTokenType(this.tokenType); restTemplate.getOAuth2ClientContext().setAccessToken(token); } return restTemplate.getForEntity(path, Map.class).getBody(); } catch (Exception ex) { this.logger.warn("Could not fetch user details: " + ex.getClass() + ", " + ex.getMessage()); return Collections.<String, Object>singletonMap("error", "Could not fetch user details"); } } }
import org.springframework.beans.factory.ObjectProvider; import org.springframework.boot.autoconfigure.security.oauth2.resource.AuthoritiesExtractor; import org.springframework.boot.autoconfigure.security.oauth2.resource.PrincipalExtractor; import org.springframework.boot.autoconfigure.security.oauth2.resource.ResourceServerProperties; import org.springframework.boot.autoconfigure.security.oauth2.resource.UserInfoRestTemplateFactory; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.http.SessionCreationPolicy; import org.springframework.security.oauth2.client.OAuth2RestOperations; import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer; import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter; import org.springframework.security.oauth2.provider.token.ResourceServerTokenServices; /** * 资源服务权限 * * @author lihy */ @Configuration @EnableResourceServer @EnableGlobalMethodSecurity(prePostEnabled = true) public class ResourceServerConfiguration extends ResourceServerConfigurerAdapter { private final ResourceServerProperties sso; private final OAuth2RestOperations restTemplate; private final AuthoritiesExtractor authoritiesExtractor; private final PrincipalExtractor principalExtractor; public ResourceServerConfiguration(ResourceServerProperties sso, UserInfoRestTemplateFactory restTemplateFactory, ObjectProvider<AuthoritiesExtractor> authoritiesExtractor, ObjectProvider<PrincipalExtractor> principalExtractor) { this.sso = sso; this.restTemplate = restTemplateFactory.getUserInfoRestTemplate(); this.authoritiesExtractor = authoritiesExtractor.getIfAvailable(); this.principalExtractor = principalExtractor.getIfAvailable(); } @Override public void configure(HttpSecurity http) throws Exception { http .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED) .and() .requestMatchers().anyRequest() .and() .cors() .and() .anonymous() .and() .authorizeRequests() .antMatchers("/client/details/**").access("#oauth2.hasAnyScope('read','write')") .antMatchers("/order/**").authenticated();//配置order访问控制,必须认证过后才可以访问 } @Bean public ResourceServerTokenServices userInfoTokenServices() { MyUserInfoTokenServices services = new MyUserInfoTokenServices( this.sso.getUserInfoUri(), this.sso.getClientId()); services.setRestTemplate(this.restTemplate); services.setTokenType(this.sso.getTokenType()); if (this.authoritiesExtractor != null) { services.setAuthoritiesExtractor(this.authoritiesExtractor); } if (this.principalExtractor != null) { services.setPrincipalExtractor(this.principalExtractor); } return services; } }
这样就可以了。
防火布
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。