WSO2 身份服务器 - Oauth 2.0 - Java 的签核示例

WSO2 Identity Server - Oauth 2.0 - Sign-off Example for Java

我为 Oauth2 身份验证流程编写了一个基于 Java 的签核例程(令牌撤销)。请参阅下面描述的手册中 cURL 协议说明的代码实现 [here]。程序代码编译和运行没有错误消息,但在注销后,用户帐户在 WSO2 仪表板查询下仍保持连接状态。

查看下面触发注销功能的Servletclass:

class SignoffServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException,IOException {

                try{
       String accessToken = (String) req.getSession().getAttribute("access_token"); 
       System.out.println("Start Logoff processing for revoke of the token: " + accessToken);
           URL url = new URL (Oauth2Server + "/oauth2/revoke?token="+accessToken); 
       HttpURLConnection connection = (HttpURLConnection) url.openConnection();
       // new encode with Apache codec (for Java8 use native lib) 
       String userCredentials = clientId + ":" + clientSecret;
       String basicAuth = "Basic " + new String(new Base64().encode(userCredentials.getBytes()));
       connection.setRequestProperty ("Authorization", basicAuth);
       connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded;charset=UTF-8");    
       connection.addRequestProperty("token", accessToken); 
       connection.addRequestProperty("token_type_hint", "access_token");
       //connection.setRequestProperty("token", accessToken); 
       // connection.setRequestProperty("token_type_hint", "access_token");
                   connection.setRequestMethod("POST");
                   connection.setDoOutput(true);
                   InputStream content = (InputStream)connection.getInputStream();
                   BufferedReader in   = 
                     new BufferedReader (new InputStreamReader (content));
                     String line;
                     while ((line = in.readLine()) != null) {
                         System.out.println(line);
                         System.out.println("Logoff finished sucessfully");
                         }
                    } catch(Exception e) {
                      System.out.println("Logoff failed, error cause: " + e.toString());
                      e.printStackTrace();
                    }
    System.out.println("Logoff finished sucessfully");
    // return the json of the user's basic info
    String html_header = "<html><body>"; 
    String myjson = "<br>Logoff completed sucessfully"; 
    myjson += "<br><br><b><a href='./index.html'>Back to login page</a></b><br>";
    String html_footer = "</body></html>";  
    String mypage = html_header + myjson + html_footer; 
    resp.setContentType("text/html");
    resp.getWriter().println(myjson);
}   

}

欢迎提出有关更改 Java 代码以激活 Oauth 2.0 签核功能的建议。

感谢您详细解释 Oauth2 中授权和身份验证之间的区别。请参阅下面能够撤销有效 Oauth2 令牌的代码:

class SignoffServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException,IOException {

    String outputl = "";        
                try{
       String accessToken = (String) req.getSession().getAttribute("access_token"); 
           // testing .. inhibu acivate this line:  // revoke accessToken = "abc";             
       System.out.println("Start Logoff processing for revoke of the token: " + accessToken);
           // URL url = new URL (Oauth2Server + "/oauth2/revoke?token="+accessToken); 
           // URL url = new URL (Oauth2Server + "/oauth2endpoints/revoke");
       URL url = new URL (Oauth2Server + "/oauth2/revoke");
       HttpURLConnection connection = (HttpURLConnection) url.openConnection();
       connection.setRequestMethod("POST");
       connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded;charset=UTF-8");
       // new encode with Apache codec (for Java8 use native lib) 
       String userCredentials = clientId + ":" + clientSecret;
       String basicAuth = "Basic " + new String(new Base64().encode(userCredentials.getBytes()));
       basicAuth = basicAuth.replace("\r", "");
       basicAuth = basicAuth.replace("\n", "");
                   connection.setRequestProperty ("Authorization", basicAuth);
       connection.setUseCaches(false);
       connection.setDoInput(true);
       connection.setDoOutput(true);
       // send data     
           // String str =  "{\"token\": \"" + accessToken + "\",\"token_type_hint\":\"access_token\"}";
       // example of JSON string  "{\"x\": \"val1\",\"y\":\"val2\"}";
       //byte[] outputInBytes = str.getBytes("UTF-8");
       //OutputStream os = connection.getOutputStream();
       //os.write( outputInBytes );    
       // os.close();
       //send request 
       DataOutputStream wr = new DataOutputStream(connection.getOutputStream()); 
       wr.writeBytes("token=" + accessToken); 
       wr.flush(); 
       wr.close(); 
        // end of new method 
                   InputStream content = (InputStream)connection.getInputStream();
                   BufferedReader in   = 
                     new BufferedReader (new InputStreamReader (content));
                     String line;
                     while ((line = in.readLine()) != null) {
                         // System.out.println(line); // for debug only 
             outputl += line; 
                         }
                    } catch(Exception e) {
                      System.out.println("Logoff failed, error cause: " + e.toString());
                      e.printStackTrace();
                    }
    System.out.println("Logoff finished successfully");
    // return the json of the user's basic info
    // customized Apache HTTP GET with header - Claude, 27 August 2015 reading user information 
    // ===============================================================================================
                String tokeninfo = ""; 
    String infourl = Oauth2Server + "/oauth2/userinfo?schema=openid";
                StringBuilder infobody = new StringBuilder();
                DefaultHttpClient infohttpclient = new DefaultHttpClient(); // create new httpClient 
                HttpGet infohttpGet = new HttpGet(infourl); // create new httpGet object
                // get some info about the user with the access token
    String currentToken = (String) req.getSession().getAttribute("access_token");
                String bearer = "Bearer " + currentToken.toString(); 
        infohttpGet.setHeader("Authorization", bearer);
    try {
           HttpResponse response = infohttpclient.execute(infohttpGet); // execute httpGet
           StatusLine statusLine = response.getStatusLine();
                   int statusCode = statusLine.getStatusCode();
                   if (statusCode == HttpStatus.SC_OK) {
                       System.out.println(statusLine);
                       infobody.append(statusLine + "\n");
                       HttpEntity e = response.getEntity();
                       String entity = EntityUtils.toString(e);
                       infobody.append(entity);
                       } else {
                              infobody.append(statusLine + "\n");
                              // System.out.println(statusLine);
                              }
                    } catch (ClientProtocolException e) {
                      e.printStackTrace();
                    } catch (IOException e) {
                      e.printStackTrace();
                    } finally {
                      tokeninfo = infobody.toString();  
                      infohttpGet.releaseConnection(); // stop connection
                    }
    // User info lookup is done fetching current log status of the token 
    if (tokeninfo.startsWith("HTTP/1.1 400 Bad Request")) { 
        tokeninfo = "Token " + currentToken + " was revoked";               
        };  
    String html_header = "<html><body>"; 
    String myjson = "<br>Logoff completed successfully"; 
    myjson += "<br>Current Userinfo and Token Status";
    myjson += "<br>" + tokeninfo + "<br>"; 
    myjson += "<br><br><b><a href='./index.html'>Back to login page</a></b><br>";
    String html_footer = "</body></html>";  
    String mypage = html_header + myjson + html_footer; 
    resp.setContentType("text/html");
    resp.getWriter().println(myjson);
    // to print signoff screen for debug purpose
    // resp.getWriter().println(outputl);
}   

}

上面的文档已经提到了撤销访问权限的方法token.Access 从 OAuth2 授权服务器撤销令牌和注销是两个不同的过程。举个例子;在 Facebook 中,您可以撤销为不同应用程序提供的访问令牌。但这并不意味着您正在退出 FB 或您已经登录的任何其他应用程序。

OAuth2 不是一种身份验证机制。它是授权框架。它不包含从授权服务器注销的标准方法。但是,您可以使用一些自定义方法从 WSO2IS 中注销(终止 WSO2IS 中的 SSO 会话)。但是,它必须通过调用以下 url 使用最终用户的浏览器(不使用后台通道)来完成。请查看 this 的最后一部分以了解更多详情

https://localhost:9443/commonauth?commonAuthLogout=true&type=oidc2&sessionDataKey=7fa50562-2d0f-4234-8e39-8a7271b9b273&commonAuthCallerPath=http://localhost:8080/openidconnect/oauth2client&relyingParty=OpenidConnectWebapp