Spring-Security-Oauth整合Spring-Security,拦截器

程序的目的主要是,在自己开发的web项目中,即提供前端页面调用访问得接口(带有安全机制),也提供第三方调用的API(基于授权认证的).

在整合的过程中发现SpringSecurity不能到即处理自己的web请求也处理第三方调用请求。所以采用拦截器拦截处理本地的web请求,spring-security-oauth对第三方认证请求进行认证与授权。如果对Oauth2.0不熟悉请参考Oauth2.0介绍,程序主要演示password模式和client模式。

官方样例:

https://github.com/spring-projects/spring-security-oauth/blob/master/samples/oauth2/sparklr/src/main/java/org/springframework/security/oauth/examples/sparklr/config/OAuth2ServerConfig.java

1.pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>springboot</groupId>
<artifactId>testSpringBoot</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>18_SpringBoot_codeStandard</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<!-- 继承父包 -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.2.RELEASE</version>
<relativePath></relativePath>
</parent>



<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--jdbc -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<!-- Spring Boot Mybatis 依赖 -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.2.0</version>
</dependency>
<!--mysql驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!--连接池 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.0.25</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.2</version>
</dependency>
       <!-- freemarker -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<!--alibab json -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.44</version>
</dependency>
   <!-- 存放token -->
    <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
             <!--security  -->
   <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
    <!--oauth  -->
<dependency>
<groupId>org.springframework.security.oauth</groupId>
<artifactId>spring-security-oauth2</artifactId>
</dependency>
<!--单元测试 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<!--maven的插件 -->
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<executable>true</executable>
</configuration>
</plugin>
</plugins>
<pluginManagement>
<plugins>
<plugin>
<!-- 配置java版本 不配置的话默认父类配置的是1.6 -->
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<!-- 配置Tomcat插件 -->
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.2</version>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>

2.application.properties中增加redis配置

#设置session超时时间
server.session.timeout=2000
spring.redis.host=127.0.0.1
spring.redis.port=6379
#配置oauth2过滤的优先级
security.oauth2.resource.filter-order=3

3.第三方调用API

package com.niugang.controller;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class OauthController {
@GetMapping("/api/product/{id}")
public String getProduct(@PathVariable String id) {
// for debug
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
return "product id : " + id;
}
@GetMapping("/api/order/{id}")
public String getOrder(@PathVariable String id) {
// for debug
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
return "order id : " + id;
}
}

AuthExceptionEntryPoint.java 自定义token授权失败返回信息

package com.niugang.exception;

import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.AuthenticationEntryPoint;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * 自定义AuthExceptionEntryPoint用于tokan校验失败返回信息
 * 
 * @author niugang
 *
 */
public class AuthExceptionEntryPoint implements AuthenticationEntryPoint {
    @Override
     public void commence(HttpServletRequest request, HttpServletResponse response,
            AuthenticationException authException) throws ServletException {

        Map<String, Object> map = new HashMap<>();
        //401 未授权
        map.put("error", "401");
        map.put("message", authException.getMessage());
        map.put("path", request.getServletPath());
        map.put("timestamp", String.valueOf(new Date().getTime()));
        response.setContentType("application/json");
        response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
        try {
            ObjectMapper mapper = new ObjectMapper();
            mapper.writeValue(response.getOutputStream(), map);
        } catch (Exception e) {
            throw new ServletException();
        }
    }
    
}

CustomAccessDeniedHandler.java 自定义token授权失败返回信息

package com.niugang.exception;

import java.io.IOException;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.web.access.AccessDeniedHandler;
import org.springframework.stereotype.Component;
import com.fasterxml.jackson.databind.ObjectMapper;

@Component
public class CustomAccessDeniedHandler implements AccessDeniedHandler {
    @Autowired
    private ObjectMapper objectMapper;

    @Override
    public void handle(HttpServletRequest request, HttpServletResponse response,
            AccessDeniedException accessDeniedException) throws IOException, ServletException {
        response.setContentType("application/json;charset=UTF-8");
        Map<String, Object> map = new HashMap<>();
        map.put("error", "403");
        map.put("message", accessDeniedException.getMessage());
        map.put("path", request.getServletPath());
        map.put("timestamp", String.valueOf(new Date().getTime()));
        response.setContentType("application/json");
        response.setStatus(HttpServletResponse.SC_FORBIDDEN);
        response.getWriter().write(objectMapper.writeValueAsString(map));
    }
}

以下为password模式通过用户名和密码获取token失败,自定义错误信息。

CustomOauthException.java

package com.niugang.exception;

import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import org.springframework.security.oauth2.common.exceptions.OAuth2Exception;

/**
 * 
 * @ClassName:  CustomOauthException   
 * @Description:password模式错误处理,自定义登录失败异常信息
 * @author: niugang
 * @date:   2018年9月5日 下午9:44:38   
 * @Copyright: [email protected]. All rights reserved. 
 *
 */
@JsonSerialize(using = CustomOauthExceptionSerializer.class)
public class CustomOauthException extends OAuth2Exception {
    public CustomOauthException(String msg) {
        super(msg);
    }
}

CustomOauthExceptionSerializer.java

package com.niugang.exception;

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.Date;
import java.util.Map;

/**
 * 
 * @ClassName:  CustomOauthExceptionSerializer   
 * @Description:password模式错误处理,自定义登录失败异常信息
 * @author: niugang
 * @date:   2018年9月5日 下午9:45:03   
 * @Copyright: [email protected]. All rights reserved. 
 *
 */
public class CustomOauthExceptionSerializer extends StdSerializer<CustomOauthException> {
    
    private static final long serialVersionUID = 1478842053473472921L;

    public CustomOauthExceptionSerializer() {
        super(CustomOauthException.class);
    }
    @Override
    public void serialize(CustomOauthException value, JsonGenerator gen, SerializerProvider provider) throws IOException {
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();

        gen.writeStartObject();
        gen.writeStringField("error", String.valueOf(value.getHttpErrorCode()));
        gen.writeStringField("message", value.getMessage());
//      gen.writeStringField("message", "用户名或密码错误");
        gen.writeStringField("path", request.getServletPath());
        gen.writeStringField("timestamp", String.valueOf(new Date().getTime()));
       if (value.getAdditionalInformation()!=null) {
            for (Map.Entry<String, String> entry : 
            value.getAdditionalInformation().entrySet()) {
                String key = entry.getKey();
                String add = entry.getValue();
                gen.writeStringField(key, add);
            }
        }
        gen.writeEndObject();
    }
}

CustomWebResponseExceptionTranslator.java

package com.niugang.exception;
import org.springframework.http.ResponseEntity;
import org.springframework.security.oauth2.common.exceptions.OAuth2Exception;
import org.springframework.security.oauth2.provider.error.WebResponseExceptionTranslator;
import org.springframework.stereotype.Component;

/**
 * 
 * @ClassName:  CustomWebResponseExceptionTranslator   
 * @Description:password模式错误处理,自定义登录失败异常信息
 * @author: niugang
 * @date:   2018年9月5日 下午9:46:36   
 * @Copyright: [email protected]. All rights reserved. 
 *
 */
@Component
public class CustomWebResponseExceptionTranslator implements WebResponseExceptionTranslator {
    @Override
    public ResponseEntity<OAuth2Exception> translate(Exception e) throws Exception {

        OAuth2Exception oAuth2Exception = (OAuth2Exception) e;
        return ResponseEntity
                .status(oAuth2Exception.getHttpErrorCode())
                .body(new CustomOauthException(oAuth2Exception.getMessage()));
    }
}

4.配置授权认证服务器

package com.niugang.config;


import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.core.userdetails.UserDetailsService;
import com.niugang.exception.AuthExceptionEntryPoint;

import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;

import org.springframework.security.oauth2.provider.token.store.redis.RedisTokenStore;

@Configuration
/*
 * 在当前应用程序上下文中启用授权服务器(即AuthorizationEndpoint和TokenEndpoint)的便利注释,
 * 它必须是一个DispatcherServlet上下文。服务器的许多特性可以通过使用AuthorizationServerConfigurer类型的@
 * bean来定制(例如,通过扩展AuthorizationServerConfigurerAdapter)。用户负责使用正常的Spring安全特性(
 * @EnableWebSecurity等)来保护授权端点(/oauth/授权),但是令牌端点(/oauth/
 * Token)将通过客户端凭证上的HTTP基本身份验证自动获得。
 * 客户端必须通过一个或多个AuthorizationServerConfigurers提供一个ClientDetailsService来注册。
 */

@EnableAuthorizationServer

public class AuthorizationServerConfiguration  extends AuthorizationServerConfigurerAdapter {
//模拟第三方调用api
private static final String DEMO_RESOURCE_ID = "api";
    @Autowired
      AuthenticationManager authenticationManager;
      @Autowired
      RedisConnectionFactory redisConnectionFactory;
      @Autowired
      private UserDetailsService userDetailsService;
      @Autowired
      private WebResponseExceptionTranslator customWebResponseExceptionTranslator;


      /**accessTokenValiditySeconds:设置token无效时间,秒
       * refreshTokenValiditySeconds:设置refresh_token无效时间秒
       */

      @Override

     public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
          //配置两个客户端,一个用于password认证一个用于client认证
          clients.inMemory().withClient("client_1")//基于客户端认证的
                  .resourceIds(DEMO_RESOURCE_ID)
                  .authorizedGrantTypes("client_credentials", "refresh_token")
                  .scopes("select")
                  .authorities("client")
                  .secret("123456")/*.refreshTokenValiditySeconds(3600).accessTokenValiditySeconds(60)*/
                  .and().withClient("client_2")//基于密码的
                  .resourceIds(DEMO_RESOURCE_ID)
                  .authorizedGrantTypes("password", "refresh_token")
                  .scopes("select")
                  .authorities("client")
                  .secret("123456")/*.refreshTokenValiditySeconds(3600).accessTokenValiditySeconds(60)*/;
                 
      }

 @Override
      public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
          endpoints
                  .tokenStore(new RedisTokenStore(redisConnectionFactory))
                  .authenticationManager(authenticationManager)
                  .userDetailsService(userDetailsService);//密码模式需要在数据库中进行认证
         endpoints.exceptionTranslator(customWebResponseExceptionTranslator);//错误异常
      }
      @Override
      public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception {
          //允许表单认证
          oauthServer.allowFormAuthenticationForClients();
          oauthServer.authenticationEntryPoint(new AuthExceptionEntryPoint());
      }
}

5.配置资源服务器

package com.niugang.config;
import org.springframework.context.annotation.Configuration;
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;
import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer;
import com.niugang.exception.AuthExceptionEntryPoint;
import com.niugang.exception.CustomAccessDeniedHandler;

/**
 * 配置资源服务器
 * 
 * @author niugang
 *
 */
@Configuration
@EnableResourceServer
/**
 * 为OAuth2资源服务器提供方便的注释,使Spring security过滤器能够通过传入的OAuth2令牌验证请求。用户应该添加这个注释,
 * 并提供一个名为ResourceServerConfigurer的@Bean(例如,通过ResourceServerConfigurerAdapter),
 * 它指定了资源的详细信息(URL路径和资源id)。为了使用这个过滤器,您必须在您的应用程序中的某个地方使用@EnableWebSecurity,
 * 或者在您使用这个注释的地方,或者在其他地方。
 * 
 * 
 *

 */

public class ResourceServerConfiguration  extends ResourceServerConfigurerAdapter{
private static final String DEMO_RESOURCE_ID = "api";
@Autowired
private CustomAccessDeniedHandler customAccessDeniedHandler;
@Override
     public void configure(ResourceServerSecurityConfigurer resources) {
//resourceId:指定可访问的资源id
//stateless:标记,以指示在这些资源上只允许基于标记的身份验证。
         resources.resourceId(DEMO_RESOURCE_ID).stateless(true);
resources.authenticationEntryPoint(new AuthExceptionEntryPoint());
        resources.accessDeniedHandler(customAccessDeniedHandler);
     }


     @Override
     public void configure(HttpSecurity http) throws Exception {
   
         http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED)
         .and()
         .authorizeRequests() 
         .antMatchers("/api/**").authenticated();//配置api访问控制,必须认证过后才可以访问
     }
}


6.配置springsecurity

package com.niugang.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;

@Configuration
@EnableWebSecurity
/**
 * 虽然和oauth认证优先级,起了冲突但是启动也会放置不安全的攻击
 * @author niugang
 *
 */
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {




@Override
protected void configure(HttpSecurity http) throws Exception {

http
             .authorizeRequests()
             .antMatchers("/oauth/**").permitAll();
}


}

7.增加拦截器

package com.niugang.interceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
public class LogInterceptor implements HandlerInterceptor {
private static Logger logger = LoggerFactory.getLogger(LogInterceptor.class);
    /**
     * 执行拦截器之前
     */
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
logger.info("interceptor....在执行前...url:{}", request.getRequestURL());
String user = (String)request.getSession().getAttribute("user");
if(user==null){
response.sendRedirect("/myweb/login");
}
return true; //返回false将不会执行了
}

/**
* 调用完处理器,渲染视图之前
*/
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
logger.info("interceptor.......url:{}", request.getRequestURL());
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
throws Exception {
}
}
 

8.配置拦截器

package com.niugang.config;
import java.util.concurrent.TimeUnit;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.CacheControl;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
@Configuration
@EnableWebMvc
public class MvcConfig extends WebMvcConfigurerAdapter {
/**
* 授权拦截的路径 addPathPatterns:拦截的路径 excludePathPatterns:不拦截的路径
*/
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new com.niugang.interceptor.LogInterceptor()).addPathPatterns("/**").excludePathPatterns("/login/**",
"/static/*","/api/**");//"/api/**",不拦截第三方调用的api
super.addInterceptors(registry);
}

/**
* 修改springboot中默认的静态文件路径
*/
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
//addResourceHandler请求路径
//addResourceLocations 在项目中的资源路径
//setCacheControl 设置静态资源缓存时间
registry.addResourceHandler("/static/**").addResourceLocations("classpath:/static/")
.setCacheControl(CacheControl.maxAge(1, TimeUnit.HOURS).cachePublic());
super.addResourceHandlers(registry);
}
}


9.配置配置springsecurity数据库认证

package com.niugang.service;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.Resource;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import com.niugang.bean.UserQuery;
import com.niugang.entity.User;
import com.niugang.exception.CheckException;
/**
 * 授权认证业务类
 * 
 * @author niugang UserDetailsService spring security包里面的
 * 重写loadUserByUsername方法
 *
 */
@Service
public class UserDetailsServiceImpl implements UserDetailsService {
//UserService自定义的,从数据查询信息
@Resource
private UserService userService;

public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
UserQuery user = new UserQuery();
user.setName(username);
// 查询用户是否存在
List<User> queryList = userService.queryListByPage(user);
if (queryList != null & queryList.size() == 1) {
// 查询用户拥有的角色
List<GrantedAuthority> list = new ArrayList<GrantedAuthority>();
//如果是admin用户登录,授予SUPERADMIN权限
if(username.equals("admin")){
list.add(new SimpleGrantedAuthority("SUPERADMIN"));
}

org.springframework.security.core.userdetails.User authUser = new org.springframework.security.core.userdetails.User(
queryList.get(0).getName(), queryList.get(0).getPassword(), list);


return authUser;
}
return null;

}
}
 

如访问:http:://localhost:8080/myweb/index,没有登录就会跳转到登录页面通过以上配置,对于所有web请求,如果没有登录都会跳转到登录页面,拦截器不会拦截调用api的请求。

访问http:://localhost:8080/myweb/api/order/1会提示没有权限需要认证,默认错误与我们自定义返回信息不一致,并且描述信息较少。那么如何自定义Spring Security Oauth2异常信息,上面也已经有代码实现

    (默认的)

(自定义的)

获取token
进行如上配置之后,启动springboot应用就可以发现多了一些自动创建的endpoints(项目启动的时候也会打印mappings):
{[/oauth/authorize]}
{[/oauth/authorize],methods=[POST]
{[/oauth/token],methods=[GET]}
{[/oauth/token],methods=[POST]}
{[/oauth/check_token]}

{[/oauth/error]

通过单元测试,获取client模式的token

package com.niugang;
import java.util.HashMap;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.ResponseEntity;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.web.client.RestTemplate;
@RunWith(SpringRunner.class)
@SpringBootTest
public class Test {

@org.junit.Test
public void  queryToken() {
    RestTemplate restTemplate = new RestTemplate();
    HashMap<String, String> hashMap = new HashMap<>();
    hashMap.put("grant_type", "client_credentials");
    hashMap.put("scope", "select");
    hashMap.put("client_id", "client_1");
    hashMap.put("client_secret", "123456");
    ResponseEntity<String> postForEntity =     restTemplate.postForEntity("http://localhost:8080/myweb/oauth/token?grant_type={grant_type}&scope={scope}&client_id={client_id}&client_secret={client_secret}",     String.class,
    String.class, hashMap);
    String body = postForEntity.getBody();
    System.out.println(body);
}
}
 


{"access_token":"5bf8c55d-874d-41fc-94bc-01e2cb8f7142","token_type":"bearer","expires_in":43199,"scope":"select"}

expires_in:访问令牌数秒内的生命周期。例如,值“3600”表示访问令牌将在响应生成后一小时内过期

然后在访问:访问http://localhost:8080/myweb/api/order/1?access_token=bbc81328-69f6-4ff0-8c4c-512f1b8beea3

密码模式也是一样就是放说需要的参数变了

注意此列中的密码模式是基于数据认证的,所以获取token之前确保数据库有对应的username和password

  /**
     * 密码模式
     */
@org.junit.Test
public void queryToken2() {
     RestTemplate restTemplate = new RestTemplate();
    HashMap<String, String> hashMap = new HashMap<>();
    hashMap.put("username", "haha");
    hashMap.put("password", "123456");
    hashMap.put("grant_type", "password");
    hashMap.put("scope", "select");
    hashMap.put("client_id", "client_2");
    hashMap.put("client_secret", "123456");
    ResponseEntity<String> postForEntity = restTemplate.postForEntity(
    "http://localhost:8080/myweb/oauth/token?username={username}&password=            {password}&grant_type={grant_type}&scope={scope}&client_id={client_id}&client_secret=        {client_secret}",
    String.class, String.class, hashMap);
    String body = postForEntity.getBody();
    System.out.println(body);
}
 

{"access_token":"39aa6302-6614-4b94-8553-a96d9ba0f893","token_type":"bearer","refresh_token":"7f2f41dd-4406-4df4-997a-d80178431db8","expires_in":43199,"scope":"select"}   //密码模式返回了refresh_token

源码地址:https://gitee.com/niugangxy/springboot

                                                                               微信公众号: 

                                               

                                                                             JAVA程序猿成长之路

                           分享资源,记录程序猿成长点滴。专注于Java,Spring,SpringBoot,SpringCloud,分布式,微服务。 

猜你喜欢

转载自www.cnblogs.com/niugang0920/p/12194910.html