zoukankan      html  css  js  c++  java
  • Spring-Security-OAuth2调用微信API

     

    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Scope;
    import org.springframework.http.HttpHeaders;
    import org.springframework.http.MediaType;
    import org.springframework.http.ResponseEntity;
    import org.springframework.http.converter.HttpMessageConverter;
    import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
    import org.springframework.security.access.AccessDeniedException;
    import org.springframework.security.oauth2.client.DefaultOAuth2ClientContext;
    import org.springframework.security.oauth2.client.OAuth2ClientContext;
    import org.springframework.security.oauth2.client.OAuth2RestTemplate;
    import org.springframework.security.oauth2.client.resource.OAuth2AccessDeniedException;
    import org.springframework.security.oauth2.client.resource.OAuth2ProtectedResourceDetails;
    import org.springframework.security.oauth2.client.resource.UserApprovalRequiredException;
    import org.springframework.security.oauth2.client.resource.UserRedirectRequiredException;
    import org.springframework.security.oauth2.client.token.AccessTokenRequest;
    import org.springframework.security.oauth2.client.token.RequestEnhancer;
    import org.springframework.security.oauth2.client.token.grant.code.AuthorizationCodeAccessTokenProvider;
    import org.springframework.security.oauth2.client.token.grant.code.AuthorizationCodeResourceDetails;
    import org.springframework.security.oauth2.common.AuthenticationScheme;
    import org.springframework.security.oauth2.common.OAuth2AccessToken;
    import org.springframework.stereotype.Controller;
    import org.springframework.util.MultiValueMap;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.ResponseBody;
    
    import javax.servlet.http.HttpServletRequest;
    import java.net.URI;
    import java.net.URISyntaxException;
    import java.util.ArrayList;
    import java.util.Arrays;
    import java.util.List;
    import java.util.Map;
    
    @Controller
    public class LoginController {
    
    
        @Autowired
        private OAuth2ClientContext context;
    
    
        @Bean
        @Scope("session")
        public OAuth2ClientContext createContext() {
            return new DefaultOAuth2ClientContext();
        }
    
    
        @ResponseBody
        @RequestMapping("/weixin/authorize")
        public Object getUserInfo(HttpServletRequest request) {
            class WeixinAuthorizationCodeAccessTokenProvider extends AuthorizationCodeAccessTokenProvider {
                public WeixinAuthorizationCodeAccessTokenProvider(List<HttpMessageConverter<?>> messageConverters) {
                    this.setMessageConverters(messageConverters);
                    this.setTokenRequestEnhancer(new RequestEnhancer() {
                        @Override
                        public void enhance(AccessTokenRequest request, OAuth2ProtectedResourceDetails resource,
                                            MultiValueMap<String, String> form, HttpHeaders headers) {
                            String clientId = form.getFirst("client_id");
                            String clientSecret = form.getFirst("client_secret");
                            form.set("appid", clientId);
                            form.set("secret", clientSecret);
                            form.remove("client_id");
                            form.remove("client_secret");
                        }
                    });
                }
    
                @Override
                public OAuth2AccessToken obtainAccessToken(OAuth2ProtectedResourceDetails details, AccessTokenRequest request)
                        throws UserRedirectRequiredException, UserApprovalRequiredException,
                        AccessDeniedException, OAuth2AccessDeniedException {
                    try {
                        return super.obtainAccessToken(details, request);
                    } catch (UserRedirectRequiredException e) {
                        Map<String, String> params = e.getRequestParams();
                        String clientId = params.get("client_id");
                        params.put("appid", clientId);
                        params.remove("client_id");
                        throw e;
                    }
                }
            }
    
            class WeixinOAuth2RestTemplate extends OAuth2RestTemplate {
    
                public WeixinOAuth2RestTemplate(AuthorizationCodeResourceDetails resource, OAuth2ClientContext context) {
                    super(resource, context);
                    List<HttpMessageConverter<?>> messageConverters = new ArrayList<HttpMessageConverter<?>>();
                    messageConverters.add(new MappingJackson2HttpMessageConverter() {
                        @Override
                        protected boolean canRead(MediaType mediaType) {
                            return true;
                        }
                    });
                    this.setMessageConverters(messageConverters);
                    this.setAccessTokenProvider(new WeixinAuthorizationCodeAccessTokenProvider(messageConverters));
                }
    
    
                @Override
                protected URI appendQueryParameter(URI uri, OAuth2AccessToken accessToken) {
                    uri = super.appendQueryParameter(uri, accessToken);
                    String url = uri.toString();
                    if (url.contains("$openid$")) {
                        String openid = (String) accessToken.getAdditionalInformation().get("openid");
                        try {
                            uri = new URI(url.replace("$openid$", openid));
                        } catch (URISyntaxException e) {
                            e.printStackTrace();
                        }
                    }
                    return uri;
                }
    
            }
    
            AuthorizationCodeResourceDetails resource = new AuthorizationCodeResourceDetails();
            resource.setAuthenticationScheme(AuthenticationScheme.form);
            resource.setClientAuthenticationScheme(AuthenticationScheme.form);
            resource.setClientId("xxxxxxxxxxx");
            resource.setClientSecret("xxxxxxxxxxx");
            resource.setUserAuthorizationUri("https://open.weixin.qq.com/connect/oauth2/authorize");
            resource.setAccessTokenUri("https://api.weixin.qq.com/sns/oauth2/access_token");
            resource.setScope(Arrays.asList("snsapi_userinfo"));
            context.getAccessTokenRequest().setCurrentUri(request.getRequestURL().toString());
    
    // resource.setPreEstablishedRedirectUri("http://www.baidu.com");
    
    // resource.setUseCurrentUri(false);
    
            OAuth2RestTemplate template = new WeixinOAuth2RestTemplate(resource, context);
            String url = "https://api.weixin.qq.com/sns/userinfo?lang=zh_CN&openid=$openid$";
            ResponseEntity<Object> result = template.getForEntity(url, Object.class);
            return result.getBody();
        }
    
    }
    https://www.cnblogs.com/kingsy/p/6375881.html

     

     

    class WeixinClientCredentialsAccessTokenProvider extends ClientCredentialsAccessTokenProvider {
        public WeixinClientCredentialsAccessTokenProvider() {
            List<HttpMessageConverter<?>> converters = new ArrayList<HttpMessageConverter<?>>();
            converters.add(new MappingJackson2HttpMessageConverter());
            this.setMessageConverters(converters);
            this.setTokenRequestEnhancer(new RequestEnhancer() {
    
                @Override
                public void enhance(AccessTokenRequest request, OAuth2ProtectedResourceDetails resource,
                                    MultiValueMap<String, String> form, HttpHeaders headers) {
                    form.set("appid", resource.getClientId());
                    form.set("secret", resource.getClientSecret());
                    form.set("grant_type", "client_credential");
                }
            });
    
        }
            OAuth2ClientContext context = new DefaultOAuth2ClientContext();
            ClientCredentialsResourceDetails resource = new ClientCredentialsResourceDetails();
            resource.setClientId("xxxxxxxxx");
            resource.setClientSecret("xxxxxxxxxxxxxxx");
            resource.setAccessTokenUri("https://api.weixin.qq.com/cgi-bin/token");
            resource.setAuthenticationScheme(AuthenticationScheme.form);
            OAuth2RestTemplate restTemplate = new OAuth2RestTemplate(resource, context);
            restTemplate.setAccessTokenProvider(new WeixinClientCredentialsAccessTokenProvider());
            restTemplate.setRetryBadAccessTokens(true);
            ResponseEntity<Object> response = restTemplate.getForEntity("https://api.weixin.qq.com/cgi-bin/user/get", Object.class);
            if (response.getStatusCode() == HttpStatus.OK) {
                System.out.println(response.getBody());
            }

    http://www.cnblogs.com/kingsy/p/6375880.html

    使用背景 :公司有个开放平台,若要访问开放平台,必须先要获取授权访问令牌(也就是下面说的:access_token)。公司的授权系统是用spring oauth2.0实现的,今天就不讲这个项目,网上比较多。今天主要是讲下如何用spring OAuth2.0 Client 组件会去实现高效获取access_token。
    以下是实现代码:

    1.项目启动后,从oauth.properties获取相关的信息(如公钥、私钥等信息),然后实例化OAuth2RestTemplate,主要是通过OAuth2RestTemplate这个类去获取access_token

    @EnableOAuth2Client
    @Configuration
    @Component
    public class Oauth2Config{
        
        private final static Logger logger = Logger.getLogger(Oauth2Config.class);
        
        private static String location = "classpath:config/*/oauth.properties";
        
        private static Map<String,String> oauthInfo = new HashMap<String,String>();
        
        @Autowired
        private OAuth2ClientContext oauth2Context;
        
        /**
         * 获取配置文件信息
         */
        static{
            ResourcePatternResolver patternResolver = new PathMatchingResourcePatternResolver();
            Resource[] resources;
            try {
                resources = patternResolver.getResources(location);
                location = resources[0].getFile().getAbsolutePath();
                logger.info("location" + location);
                Properties props = new Properties();  
                try {  
                    if(location.contains("dev")){
                        props = PropertiesLoaderUtils.loadAllProperties("config/dev/oauth.properties");
                    }else if(location.contains("test")){
                        props = PropertiesLoaderUtils.loadAllProperties("config/test/oauth.properties");
                    }else if(location.contains("production")){
                        props = PropertiesLoaderUtils.loadAllProperties("config/production/oauth.properties");
                    }
                    for(Object key:props.keySet()){  
                        logger.warn(key + " : " +  (String)props.get(key));
                        oauthInfo.put((String) key, (String)props.get(key));
                    }  
                } catch (IOException e) {  
                    System.out.println(e.getMessage());  
                }  
            } catch (IOException e) {
                e.printStackTrace();
            }
            
        } 
        
        
        @Bean
        public AccessTokenRequest accessTokenRequest(){
            AccessTokenRequest defaultAccessTokenRequest = new DefaultAccessTokenRequest();
            Map<String, List<String>> headers = new HashMap<String, List<String>>();
            List<String> headerList=new ArrayList<String>();
            headerList.add("Basic " + oauthInfo.get("public_key"));
            headers.put("Authorization", headerList);
            defaultAccessTokenRequest.setHeaders(headers);
            defaultAccessTokenRequest.setCurrentUri(oauthInfo.get("redirect_uri"));
            return defaultAccessTokenRequest;
        }
        
        @Bean
        public AuthorizationCodeResourceDetails resourceDetails(){
            AuthorizationCodeResourceDetails resource = new AuthorizationCodeResourceDetails();
            resource.setAccessTokenUri(oauthInfo.get("oauth_url") + oauthInfo.get("request_and_refresh_token"));
            resource.setClientId(oauthInfo.get("client_id"));
            resource.setGrantType("authorization_code");
            resource.setUserAuthorizationUri(oauthInfo.get("oauth_url") + oauthInfo.get("request_code_url"));
            resource.setScope(Arrays.asList("app"));
            resource.setPreEstablishedRedirectUri(oauthInfo.get("redirect_uri"));
            return resource;
        }
        
        @Bean
        public OAuth2RestTemplate oAuth2RestTemplate(){
            accessTokenRequest().setPreservedState(oauthInfo.get("redirect_uri"));
            accessTokenRequest().setStateKey(new DefaultStateKeyGenerator().generateKey(resourceDetails()));
            
            AuthorizationCodeAccessTokenProvider provider = new AuthorizationCodeAccessTokenProvider();
            provider.setAuthenticationHandler(new ClientAuthenticationHandler() {
                @Override
                public void authenticateTokenRequest(
                        OAuth2ProtectedResourceDetails resource,
                        MultiValueMap<String, String> form, HttpHeaders headers) {
                    headers.set("Authorization", "Basic " + oauthInfo.get("private_key") );
                }
            });
            AccessTokenProviderChain providerChain = new AccessTokenProviderChain(Arrays.asList(provider));
            //oauth2Context.setPreservedState(accessTokenRequest().getStateKey(),accessTokenRequest().getPreservedState());
            OAuth2RestTemplate template=new OAuth2RestTemplate(resourceDetails(),oauth2Context);
            template.setAccessTokenProvider(providerChain);
            return template;
        }
    
        
    }

    2.通过OAuth2RestTemplate去获取access_token的值,之所以每次都情况授权code,是因为spring oauth2授权code只能用一次便废弃,然后起OAuth2ClientContext类又不主动清空code,这里我只能自己手动清除。

    @Component
    public class AccessTokenUtils {
    
        private final static Logger logger = Logger.getLogger(AccessTokenUtils.class);
        
        
        @Autowired
        private OAuth2RestTemplate restTemplate;
        
        @Autowired
        private Oauth2Config oauth2Config;
        
        
        /**
         * 获取oauth2的授权令牌access_token
         * @return
         */
        public  String getAccessToken(){
            logger.info("获取oauth2的授权令牌access_token start ...");
            OAuth2ClientContext oAuth2ClientContext = restTemplate.getOAuth2ClientContext();
            oAuth2ClientContext.getAccessTokenRequest().setAuthorizationCode(null);//清空授权code
            String stateKey = oAuth2ClientContext.getAccessTokenRequest().getStateKey();
            Object preservedState = oAuth2ClientContext.getAccessTokenRequest().getPreservedState();
            if(StringUtils.isEmpty(stateKey))
                stateKey = new DefaultStateKeyGenerator().generateKey(oauth2Config.resourceDetails());
            if(preservedState == null )
                preservedState = VipConstant.redirtUrl;
            
            logger.info("statekey:" + stateKey + " ; preservedState : " + preservedState);
            oAuth2ClientContext.setPreservedState(oAuth2ClientContext.getAccessTokenRequest().getStateKey(), oAuth2ClientContext.getAccessTokenRequest().getPreservedState());
            OAuth2AccessToken oAuth2AccessToken = this.restTemplate.getAccessToken();
            String access_token = oAuth2AccessToken.getValue();
            logger.info("获取oauth2的授权令牌access_token end ;access_token = " +  access_token + ";失效时间 = " + oAuth2AccessToken.getExpiration() + " ;剩余失效时间:" + oAuth2AccessToken.getExpiresIn() );
            return access_token;
        }
        
    }

    3.以下配置是授权服务给配置的

    #==================spring oauth2.0=====================================
    #客户端ID
    client_id=xxx
    #公钥(BASE64(xx))
    public_key=xxx
    #私钥(BASE64(xx))
    private_key=xx
    #spring oauth2.0服务url
    oauth_url=xxx
    #获取请求code URL
    request_code_url=oauth/authorize
    #获取请求token或刷新token URL
    request_and_refresh_token=oauth/token
    #回调地址
    redirect_uri=http://www.baidu.com

    Spring OAuth2.0 Client官网地址:http://projects.spring.io/spring-security-oauth/docs/oauth2.html





  • 相关阅读:
    leetcode_question_67 Add Binary
    几种常用控件的使用方法
    JavaBean讲解 规范
    [置顶] JDK-CountDownLatch-实例、源码和模拟实现
    恋人分手后需要做的不是挽回而是二次吸引
    leetcode_question_70 Climbing Stairs
    偶然碰到的Win7 64位下CHM 的问题解决
    FTP中各文件目录的说明
    深入理解line-height与vertical-align(1)
    行内元素和块级元素
  • 原文地址:https://www.cnblogs.com/softidea/p/8000921.html
Copyright © 2011-2022 走看看