Spring MVC 拦截器方式示例

客户端直接通过拦截器的方式与服务端进行交互,当请求中没有access_token 信息, 则进入统一身份认证授权登录界面,登录完成后,会重定向回传递的redirect_uri地址,来完成交互

1、判断请求是否包含 access_token 信息,没有则拦截到授权页面

https://cas_server_url/oauth2.0/authorize?response_type=token&client_id=clientxxx&redirect_uri=https://my_server_url/callback

2、授权成功后将会重定向 https://my_server_url/callback#token=access_token

编写登录回调接口 /callback ,存储 access_token(可前端存储)

3、认证回调接口获取到 access_token 后,可获取当前登陆人信息

根据 accesstoken 获取用户信息:https://cas_server_url/oauth2.0/profile?access_token=xxxxx

正确时返回:

{
  "service" : "service_url",
  "attributes" : {
    "credentialType" : "LoginCredential"
  },
  "id" : "admin",
  "client_id" : "client"
}

响应参数

参数名称 参数说明 类型 schema
service 应用地址 string
attributes 用户属性值 integer(int64)
id 用户唯一ID string
client_id 应用客户端ID string

代码示例


import com.alibaba.fastjson2.JSONObject;
import lombok.extern.slf4j.Slf4j;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import org.apache.http.NameValuePair;
import org.apache.http.client.utils.URLEncodedUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.charset.Charset;
import java.util.List;
import java.util.Optional;

@Slf4j
public class CasAuthInterceptor implements HandlerInterceptor {

    /**
     * HTTP Authorization Param, equal to <code>accessToken</code>
     */
    public static final String AUTHORIZATION_PARAM = "access_token";

    public OkHttpClient okhttp3Client;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("preHandle......");

        // 1、获取请求中的accessToken
        String accessToken = this.obtainaAccessToken(request);
        if(StringUtils.hasText(accessToken)){

            // 2、创建Request.Builder对象
            long startTime = System.currentTimeMillis();
            Request.Builder builder = new Request.Builder().url("https://cas_server_url/oauth2.0/profile?access_token=" + accessToken);
            // 2.创建一个call对象, 参数就是Request请求对象
            try {
                Response okResponse = okhttp3Client.newCall(builder.get().build()).execute();
                if (okResponse.isSuccessful()) {
                    log.info("OkHttp3 >> Request Success : code : {}, use time : {} ", okResponse.code(), System.currentTimeMillis() - startTime);
                    /**
                     {
                     "service" : "service_url",
                     "attributes" : {
                     "credentialType" : "LoginCredential"
                     },
                     "id" : "admin",
                     "client_id" : "client"
                     }
                     */
                    String body = okResponse.body().string();
                    JSONObject jsonObject = JSONObject.parseObject(body);
                    // 接入的客户端ID
                    String clientId = jsonObject.getString("client_id");
                    // 当前认证用户信息
                    JSONObject attributes = jsonObject.getJSONObject("attributes");
                } else {
                    log.error("OkHttp3 >> Request Failure : code : {}, message : {}, use time : {} ", okResponse.code(), okResponse.message(), System.currentTimeMillis() - startTime);
                }
            } catch (Exception e) {
                log.error("OkHttp3 Request Error : {}, use time : {}", e.getMessage(), System.currentTimeMillis() - startTime);
            }
            return true;
        }
        response.sendRedirect("https://cas_server_url/oauth2.0/authorize?response_type=token&client_id=clientxxx&redirect_uri=https://my_server_url/callback");
        return false;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("postHandle......");
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("afterCompletion......");
    }

    protected String obtainaAccessToken(HttpServletRequest request) throws URISyntaxException {
        // 从header中获取AcessToken
        URI uri = new URI(request.getRequestURL().toString());
        // https://my_server_url/callback#token=access_token
        System.out.println(uri.getFragment());
        List<NameValuePair> valuePairList = URLEncodedUtils.parse(uri.getFragment(), Charset.defaultCharset());
        Optional<NameValuePair> optional = valuePairList.stream().filter(nameValuePair -> nameValuePair.getName().equals("token")).findFirst();
        if(optional.isPresent()){
            return optional.get().getValue();
        }
        String accessToken = request.getParameter(AUTHORIZATION_PARAM);
        return accessToken;
    }


}
作者:Jeebiz  创建时间:2022-10-23 20:28
最后编辑:Jeebiz  更新时间:2024-05-07 20:29