spring cloud oauth2(四) 资源服务搭建

依赖

和server依赖一样

SecurityConfig配置

package com.Lonni.resource.config;

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.annotation.web.configuration.WebSecurityConfigurerAdapter;

@Configuration
//开启权限注解
@EnableGlobalMethodSecurity(securedEnabled = true,prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().disable()
                .authorizeRequests()
                .anyRequest().permitAll();
    }

}

ResourceServerConfigurerAdapter 配置

package com.Lonni.resource.config;


import cn.hutool.core.util.ArrayUtil;
import com.Lonni.resource.exception.Auth2ResponseExceptionTranslator;
import com.Lonni.resource.model.IgnorenPath;
import org.apache.commons.lang.ArrayUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer;
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 org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.security.web.access.AccessDeniedHandler;

import java.util.Arrays;

/**
 * @program: Lonni-plus
 * @description: 配置资源服务(主要配置类) 继承自 ResourceServerConfigurerAdapter
 * @author: lonni
 * @create: 2020-11-19 21:22
 */
@Configuration
@EnableResourceServer
public class ResourceServiceConfig extends ResourceServerConfigurerAdapter {

    /**
     * 1:注入token存储器  tokenconfig中
     */
    @Autowired
    @Qualifier("jwtTokenStore")
    private TokenStore tokenStore;

    /**
     * 2: 注入token解密器 tokenconfig中
     */
    @Autowired
    @Qualifier("jwtAccessTokenConverter")
    private JwtAccessTokenConverter tokenConverter;


    //@Autowired
   // IgnorenPath ignorenPath;


    @Autowired
    AccessDeniedHandler accessDeniedHandler;



    /**
     * 配置token解析和资源id
     * @param resources
     * @throws Exception
     */
    @Override
    public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
      //这里的资源id从配置文件中读取
        resources .resourceId(ignorenPath.getId())
                //配置token存储
                .tokenStore(tokenStore)
                //是否吧token记录在session中
                .stateless(true);

        // 定义异常转换类生效
        AuthenticationEntryPoint authenticationEntryPoint = new OAuth2AuthenticationEntryPoint();
        ((OAuth2AuthenticationEntryPoint) authenticationEntryPoint)
                .setExceptionTranslator(new Auth2ResponseExceptionTranslator());
         resources.authenticationEntryPoint(authenticationEntryPoint)
                   .accessDeniedHandler(accessDeniedHandler);

    }

    /**
     * 配置资源服务需要拦截的请求 可以在这里增加白名单配置
     * @param http
     * @throws Exception
     */
    @Override
    public void configure(HttpSecurity http) throws Exception {
        String[] allIgnoredPath = ignorenPath.getAllIgnoredPath();

        http.authorizeRequests().
                //设置白名单 其他全部都需要权限访问
            // antMatchers(allIgnoredPath)
                .permitAll()
        .anyRequest().authenticated();
    }
}

异常捕获类

AccessDeniedHandler 授权拒绝错误处理类
package com.Lonni.resource.exception;

import com.Lonni.common.viewmodels.AjaxResult;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.extension.api.R;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.SneakyThrows;
import org.springframework.http.HttpStatus;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.oauth2.provider.error.OAuth2AccessDeniedHandler;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.PrintWriter;

/**
 * @descriptions:
 * @author: Lonni
 * @date: 2021/1/24 15:53
 * @version: 1.0
 */
@Component
public class AccessDeniedHandler extends OAuth2AccessDeniedHandler {

    /**
     * 授权拒绝处理
     */
    @Override
    @SneakyThrows
    public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException authException) {
        response.setCharacterEncoding("UTF-8");
        response.setContentType("application/json; charset=utf-8");

        AjaxResult result=   AjaxResult.FAIL("权限错误");
        response.setStatus(HttpStatus.UNAUTHORIZED.value());
        PrintWriter printWriter = response.getWriter();
        printWriter.append(JSON.toJSONString(result));
    }


}
资源认证异常处理 Auth2ResponseExceptionTranslator
package com.Lonni.resource.exception;

import com.Lonni.common.viewmodels.AjaxResult;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.authentication.InsufficientAuthenticationException;
import org.springframework.security.oauth2.client.resource.OAuth2AccessDeniedException;
import org.springframework.security.oauth2.common.exceptions.InvalidTokenException;
import org.springframework.security.oauth2.common.exceptions.OAuth2Exception;
import org.springframework.security.oauth2.provider.error.WebResponseExceptionTranslator;

/**
 * 资源认证异常处理
 */
public class Auth2ResponseExceptionTranslator implements WebResponseExceptionTranslator {
    @Override
    public ResponseEntity<OAuth2Exception> translate(Exception throwable) throws Exception {
        throwable.printStackTrace();
        String message=throwable.getMessage();

        if (throwable instanceof InvalidTokenException) {
            if (message.contains("Access token expired")){
                return new ResponseEntity(
                        AjaxResult.FAIL("token已过期") , HttpStatus.FORBIDDEN);
            }
            return new ResponseEntity(
                    AjaxResult.FAIL("token不正确") , HttpStatus.FORBIDDEN);
        }
        if (throwable instanceof OAuth2AccessDeniedException) {
            String resourceid=message.substring(message.lastIndexOf("(")+1,message.lastIndexOf(")"));
            return new ResponseEntity(
                    AjaxResult.FAIL("您没有资源:["+resourceid+"]访问的权限!") , HttpStatus.FORBIDDEN);
        }
        if (throwable instanceof InsufficientAuthenticationException){
            System.out.println("is InsufficientAuthenticationException");
            return new ResponseEntity(
                    AjaxResult.FAIL("身份票据不合法,请登录!") , HttpStatus.FORBIDDEN);
        }

        return new ResponseEntity(AjaxResult.FAIL("权限错误"), HttpStatus.FORBIDDEN);
    }
}
ControllerAdvice处理
package com.Lonni.resource.exception;

import com.Lonni.common.viewmodels.AjaxResult;
import com.Lonni.core.utils.PrintStatckUtil;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.authentication.InsufficientAuthenticationException;
import org.springframework.security.oauth2.client.resource.OAuth2AccessDeniedException;
import org.springframework.security.oauth2.common.exceptions.InvalidTokenException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;

/**
 * @author lonni
 * @Description: TODO
 * @date 2020/11/1917:49
 */
@ControllerAdvice
public class ResourceAdviceHandle {


    @ExceptionHandler(value = AccessDeniedException.class)
    @ResponseBody
    public AjaxResult AccessDeniedException(AccessDeniedException ex) {
        PrintStatckUtil.consolePrintIsDebug(ex);
        return AjaxResult.FAIL("权限不足,"+ex.getMessage());
    }

    @ExceptionHandler(value = InvalidTokenException.class)
    @ResponseBody
    public AjaxResult invalidTokenException(InvalidTokenException ex) {
        PrintStatckUtil.consolePrintIsDebug(ex);
        return AjaxResult.FAIL("token不正确");
    }


    @ExceptionHandler(value ={ InsufficientAuthenticationException.class, OAuth2AccessDeniedException.class})
    @ResponseBody
    public AjaxResult insufficientAuthenticationException(Exception ex) {
        PrintStatckUtil.consolePrintIsDebug(ex);
        String message = ex.getMessage();
        if (message.contains("Access token expired")){
            return AjaxResult.FAIL("token已失效");
        }
        if (message.contains("resource id")){
            String resourceid=message.substring(message.lastIndexOf("("),message.lastIndexOf(")"));
            return AjaxResult.FAIL("您没有资源:["+resourceid+"]的访问权限!");
        }
        return  AjaxResult.FAIL(message);
    }

}
原文地址:https://www.cnblogs.com/HiLzd/p/14367883.html