改造和授权饼干

Posted

技术标签:

【中文标题】改造和授权饼干【英文标题】:RETROFIT & AUTH COOKIE 【发布时间】:2014-02-10 06:29:05 【问题描述】:

我需要知道如何在改造中添加授权 cookie 标头。我已经看到了使用请求拦截器等的建议。下面是我正在尝试的,但这是正确的吗?首先,我已经需要一个 RequestAdatper 来第一次获取会话 ID。这只能由请求适配器的构建器设置。但我首先需要提出一个请求来获取会话 ID。我是否需要两个休息适配器,一个来获取 sessionId,另一个在我获得它之后。我真正需要的是适配器上的一种方法来设置cookie,但它似乎不是这样的方法。这越来越尴尬了。如何在改造中设置授权 cookie?我在常见问题解答或教程中没有看到这一点。

RequestInterceptor requestInterceptor = new RequestInterceptor()
   
   @Override
   public void intercept(RequestFacade request) 
        request.addHeader("Set-Cookie", "sessionId="+sessionIdentifier);
   
 ;

RestAdapter.Builder().setServer(serverURL)..setRequestIntercepter(requestIntercepter).build();  

// but I don't have sessionId when this is first issued ???

【问题讨论】:

我的应用可能不需要这个。但这是一个很好的问题,所以请有人回答。 你最终做了什么,因为答案中的代码令人困惑......试图将它包含在我调用我的请求的同一页面中。 【参考方案1】:

保留对拦截器的引用,并将其视为单例,就像您自己是 RestAdapter 一样。

public class ApiHeaders implements RequestInterceptor 
  private String sessionId;

  public void setSessionId(String sessionId) 
    this.sessionId = sessionId;
  

  public void clearSessionId() 
    sessionId = null;
  

  @Override public void intercept(RequestFacade request) 
    if (sessionId != null) 
      request.setHeader(...);
    
  

现在,只需在您的身份验证调用后调用setSessionId。所有后续请求都将包含标头。

【讨论】:

试图弄清楚如何从类外部调用 setSessionId...ApiHeaders.setSessionId 不是方法... @Lion789 你需要一个静态的 setSessionId。 @Jake Wharton:我们如何从响应中获取 sessionId? 这将取决于您的服务器如何将它们发回。 @KailashDabhi 你只需要使用拦截器并覆盖新方法!【参考方案2】:

你可以像这样获取cookies

 public class MyCookieManager extends CookieManager 

    @Override
    public void put(URI uri, Map<String, List<String>> stringListMap) throws IOException 
        super.put(uri, stringListMap);
        if (stringListMap != null && stringListMap.get("Set-Cookie") != null)
            for (String string : stringListMap.get("Set-Cookie")) 
                if (string.contains("JSESSIONID")) 
                    Preference.getInstance().setSessionId(string);
                
            
    

使用它来设置 CookieHandler

 MyCookieManager myCookieManager = new MyCookieManager();
        CookieHandler.setDefault(myCookieManager);

然后在你的请求拦截器中像这样使用它

 String sessionId = preference.getSessionId();
                    if (sessionId != null)
                        requestFacade.addHeader(Cookie, sessionId);

【讨论】:

工作得很好!谢谢@Chetna!【参考方案3】:

第 1 步。解析响应标头。 在覆盖的success 方法中在您的回调中调用此方法。

    /**
     * Method extracts cookie string from headers
     * @param response with headers
     * @return cookie string if present or null
     */
    private String getCookieString(Response response) 
        for (Header header : response.getHeaders()) 
            if (null!= header.getName() && header.getName().equals("Set-Cookie")) 
                return header.getValue();
            
        
        return null;
    

第 2 步。编写一些静态类或单例来保存 cookie 和您的 RequestInterceptor 实例。在 RequestInterceptor 内部覆盖拦截方法以将您的 cookie 添加到 Header。

public class RestAdapter 
    private static String cookies;

    public static String getCookies() 
        return cookies;
    

    public static void setCookies(String cookies) 
        RestAdapter.cookies = cookies;
    

    /**
     * Injects cookies to every request
     */
    private static final RequestInterceptor COOKIES_REQUEST_INTERCEPTOR = new RequestInterceptor() 
        @Override
        public void intercept(RequestFacade request) 
            if (null != cookies && cookies.length() > 0) 
                request.addHeader("Cookie", cookies);
            
        
    ;

    public static final RestInterface getService() 
        return new RestAdapter.Builder()
                .setEndpoint(Config.ENDPOINT)
                .setRequestInterceptor(COOKIES_REQUEST_INTERCEPTOR)
                .setConverter(new JacksonConverter())
                .setLogLevel(RestAdapter.LogLevel.NONE)
                .build()
                .create(RestInterface.class);
    

【讨论】:

【参考方案4】:

根据@sbtgE 的回答,但有一些更正。 CookieHandler.getDefault() 可能为空,所以我使用 CookieManager。

应用的 build.gradle:

dependencies 
    ...
    compile 'com.squareup.okhttp3:okhttp-urlconnection:3.4.1'

设置改造:

service = new Retrofit.Builder()
        .baseUrl(/* your base URL */)
        .addConverterFactory(/* your favourite converter */)
        .client(
                new OkHttpClient.Builder()
                        // this line is the important one:
                        .cookieJar(new JavaNetCookieJar(new CookieManager()))
                        .build())
        .build()
        .create(YourInterface.class);

【讨论】:

断线时如何清除cookie。【参考方案5】:

使用 lib 的简单解决方案。编译com.squareup.okhttp3:okhttp-urlconnection:3.2.0

JavaNetCookieJar jncj = new JavaNetCookieJar(CookieHandler.getDefault()); OkHttpClient.Builder().cookieJar(jncj).build();

【讨论】:

以上是关于改造和授权饼干的主要内容,如果未能解决你的问题,请参考以下文章

Spring cloud微服务安全实战-6-5jwt改造之日志及错误处理

OAuth2.0四种授权模式

Retrofit2:如何使授权令牌标头动态化?

微服务之间的通讯安全-JWT优化之日志错误处理限流及JWT改造后执行流程梳理

速达软件二次开发-订单可以按照授权用户开,新增图片

Spring security登录授权用户有效期简单例子