• 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: 863263957@qq.com. 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: 863263957@qq.com. 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: 863263957@qq.com. 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

     微信公众号

     

     

  • 相关阅读:
    ElasticSearch入门到筋痛
    JavaScript学习(四)
    JavaScript学习(三)
    JavaScript学习(二)
    JavaWeb学习(一)
    final
    static
    object的方法
    java 数据类型
    spring mvc
  • 原文地址:https://www.cnblogs.com/niugang0920/p/12194910.html
Copyright © 2020-2023  润新知