powerbi 用户名密码认证和服务主体认证区别
1. 主要区别
主要区别在于token的作用域不同。
1.1 用户密码
通过用户名称和密码可以直接获取一个access_token(代码见下面),这个token可以用于powerbi 报表和数据集的所有操作;
1.2 服务主体认证
先生成一个acess_token,这个token有获取所有报表属性的权限,没有嵌入报表、新增、编辑报表的权限;
根据这个access_token 和下面的API可以生成新的token,用于嵌入报表、新增、编辑报表,API翻译如下:
注意:需要.com改成.cn
OPERATIONS
1.Dashboards GenerateTokenInGroup // 创建一个token,用于查看指定的dashboard
POST https://api.powerbi.com/v1.0/myorg/groups/{groupId}/dashboards/{dashboardId}/GenerateToken
// 嵌入报表
2.Datasets GenerateTokenInGroup // 创建一个token,用于嵌入报表在指定的数据集
POST https://api.powerbi.com/v1.0/myorg/groups/{groupId}/datasets/{datasetId}/GenerateToken
BODY {"accessLevel":"Create/Edit/View","allowSaveAs":true} 【Create报错】
3.Generate Token // 为多个报表、数据、工作空间,创建一个token,
POST https://api.powerbi.com/v1.0/myorg/GenerateToken
// 新增报表
4.Reports GenerateTokenForCreateInGroup // 创建一个token,用于创建报表在指定的数据集
POST https://api.powerbi.com/v1.0/myorg/groups/{groupId}/reports/GenerateToken
BODY {"accessLevel":"Create/Edit/View","allowSaveAs":true,"datasetId":"必填"}
// 查看或编辑报表
5.Reports GenerateTokenInGroup // 创建一个token,用于查看或编辑指定的报表
POST https://api.powerbi.com/v1.0/myorg/groups/{groupId}/reports/{reportId}/GenerateToken
BODY {"accessLevel":"Create/Edit/View","allowSaveAs":true}
原文参考
https://docs.microsoft.com/en-us/rest/api/power-bi/embedtoken/dashboards_generatetokeningroup
2.用户名密码获取token代码
/**
* 通过密码获取token
*
* @return token
*/
public String getPasswordToken() {
String token = "";
String url = "https://login.partner.microsoftonline.cn/common/oauth2/token";
Map<String, String> header = new HashMap<>(4);
header.put("Content-Type", "application/x-www-form-urlencoded");
header.put("Accept", "*/*");
Map<String, String> body = new HashMap<>(16);
body.put("resource", "https://analysis.chinacloudapi.cn/powerbi/api");
body.put("client_id", "xxx");
body.put("client_secret", "xxx");
body.put("grant_type", "password");
body.put("username", "xxx");
body.put("password", "xxx");
StringBuilder bodyStr = new StringBuilder();
int i = 0;
for (Map.Entry<String, String> entry : body.entrySet()) {
i++;
bodyStr.append(entry.getKey()).append("=").append(entry.getValue());
if (i < body.size()) {
bodyStr.append("&");
}
}
String baseStr = httpUtil.doPost(url, header, bodyStr.toString());
JSONObject jsonObject = JSONObject.parseObject(baseStr);
token = jsonObject.getString("access_token");
return token;
}
3. 服务主体认证获取token
3.1 controller
/**
* 生成embedToken用于powerbi操作
*
* @param type 数据类型,dataset/report/accessToken(获取原始的accessToken)
* @param id 操作对象的id datasetId/reportId
* @param level token类型枚举:Create创建, Edit编辑,View查看
* @return token
* @throws Exception
* @author: leiming5
*/
@ApiOperation("生成all Token用于powerbi操作")
@GetMapping("/bi/all/token")
public Result allToken(
@ApiParam(value = "数据类型", required = true) @RequestParam("type") String type,
@ApiParam(value = "数据id") @RequestParam(value = "id",required = false) String id,
@ApiParam(value = "token类型") @RequestParam(value = "level",required = false) String level) throws Exception {
return powerBiService.allToken(type, id, level);
}
3.2 service
/**
* 生成embedToken用于powerbi操作
*
* @param type 数据类型,dataset/report
* @param id 操作对象的id datasetId/reportId
* @param level token类型枚举:Create创建, Edit编辑,View查看
* @return token
* @throws Exception
* @author: leiming5
*/
Result allToken(String type, String id, String level) throws Exception;
3.3 serviceImpl
/**
* 生成embedToken用于powerbi操作
*
* @param type 数据类型,dataset/report
* @param id 操作对象的id datasetId/reportId
* @param level token类型枚举:Create创建, Edit编辑,View查看
* @return token
* @throws Exception
* @author: leiming5
*/
@Override
public Result allToken(String type, String id, String level) throws Exception {
/**
* 生成所有操作的token(report的增加、删除、修改、查看(嵌入))
* 1. 增加
* POST https://api.powerbi.com/v1.0/myorg/groups/{groupId}/reports/GenerateToken
* BODY {"accessLevel":"Create/Edit/View","allowSaveAs":true,"datasetId":"必填"}
*
* 2. 查看(嵌入报表)或编辑报表
* POST https://api.powerbi.com/v1.0/myorg/groups/{groupId}/reports/{reportId}/GenerateToken
* BODY {"accessLevel":"Create/Edit/View","allowSaveAs":true}
*/
String token = "";
// 查看(嵌入报表)或编辑报表
if ("report".equals(type)) {
List<String> operator = Arrays.asList("View", "Edit");
if (operator.contains(level)) {
token = powerBIUtil.generateTokenByReportId(id, level);
}
} else if ("accessToken".equals(type)) {
// 生成原始的 accessToken
token = powerBIUtil.getEmailToken();
} else if ("all".equals(type)) {
// dataset 创建报表页面渲染
token = powerBIUtil.generateTokenByDatasetIds(id);
} else if ("dataset".equals(type) && "Create".equals(level)) {
// 新增报表
token = powerBIUtil.generateTokenByDatasetId(id, level);
}
return Result.d(token);
}
3.4 powerBIUtil
/**
* 根据世纪互联电子邮件中,提供的接口获取token
*
* @return access token
*/
public String getEmailToken() {
String token = "";
String url = "https://login.chinacloudapi.cn/a6c1b34e-d17f-48de-83b8-8e248b0f0360/oauth2/token";
Map<String, String> header = new HashMap<>(16);
header.put("Content-Type", "application/x-www-form-urlencoded");
header.put("Accept", "*/*");
Map<String, String> body = new HashMap<>(16);
body.put("grant_type", "client_credentials");
body.put("resource", "https://analysis.chinacloudapi.cn/powerbi/api");
body.put("client_id", "xxx");
body.put("client_secret", "xxx");
StringBuilder bodyStr = new StringBuilder();
int i = 0;
for (Map.Entry<String, String> entry : body.entrySet()) {
i++;
bodyStr.append(entry.getKey()).append("=").append(entry.getValue());
if (i < body.size()) {
bodyStr.append("&");
}
}
String baseStr = httpUtil.doPost(url, header, bodyStr.toString());
JSONObject jsonObject = JSONObject.parseObject(baseStr);
token = jsonObject.getString("access_token");
return token;
}
/**
* 根据世纪互联电子邮件中教材api,生成embedToken
*
* @return embedToken
* @author: leiming5
*/
public String generateTokenByReportId(String id, String level) throws Exception {
String url = "https://api.powerbi.cn/v1.0/myorg/groups/fecd78a9-73f5-49c9-ae8d-40bd3590112e/reports/";
url = url + id;
url = url + "/GenerateToken";
JSONObject body = new JSONObject();
body.put("accessLevel", level);
body.put("allowSaveAs", "true");
String accessToken = getToken();
String baseStr = httpUtil.postByUrlAndToken(url,accessToken, body);
JSONObject jsonObject = JSONObject.parseObject(baseStr);
return jsonObject.getString("token");
}
/**
* 根据世纪互联电子邮件中教材api,生成embedToken
*
* @return embedToken
* @author: leiming5
*/
public String generateTokenByDatasetId(String datasetId, String level) throws Exception {
String url = "https://api.powerbi.cn/v1.0/myorg/groups/fecd78a9-73f5-49c9-ae8d-40bd3590112e/reports/GenerateToken";
JSONObject body = new JSONObject();
body.put("accessLevel", level);
body.put("allowSaveAs", "true");
body.put("datasetId", datasetId);
String accessToken = getToken();
String baseStr = httpUtil.postByUrlAndToken(url,accessToken, body);
JSONObject jsonObject = JSONObject.parseObject(baseStr);
return jsonObject.getString("token");
}
/**
* 生成所有的token
*
* @param datasetId 数据集id
* @return token
* @throws Exception
* @author: leiming5
*/
public String generateTokenByDatasetIds(String datasetId) throws Exception {
String url = "https://api.powerbi.cn/v1.0/myorg/GenerateToken";
JSONObject body = new JSONObject();
List<JSONObject> list = new ArrayList<>();
JSONObject dataSet = new JSONObject();
dataSet.put("id", datasetId);
list.add(dataSet);
body.put("datasets", list);
String accessToken = getToken();
String baseStr = httpUtil.postByUrlAndToken(url,accessToken, body);
JSONObject jsonObject = JSONObject.parseObject(baseStr);
return jsonObject.getString("token");
}
3.5 HttpUtil
import com.alibaba.fastjson.JSONObject;
import lombok.extern.log4j.Log4j;
import org.springframework.stereotype.Component;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Map;
/**
* 设置连接超时时间,20000,消除魔术数字
*/
private static final int TWOTHOUSAND = 20000;
/**
* 发送post请求
*
* @param url 请求路径
* @param header 请求头
* @param body 请求体
* @return String
*/
public String doPost(String url, Map<String, String> header, String body) {
String result = "";
BufferedReader in = null;
PrintWriter out = null;
try {
// 设置 url
URL realUrl = new URL(url);
HttpURLConnection connection = (HttpURLConnection) realUrl.openConnection();
connection.setRequestMethod("POST");
// 设置 header
for (Map.Entry<String, String> entry : header.entrySet()) {
connection.setRequestProperty(entry.getKey(), entry.getValue());
}
// 设置请求 body
connection.setDoOutput(true);
connection.setDoInput(true);
//设置连接超时和读取超时时间
connection.setConnectTimeout(TWOTHOUSAND);
connection.setReadTimeout(TWOTHOUSAND);
try {
out = new PrintWriter(connection.getOutputStream());
// 保存body
out.print(body);
// 发送body
out.flush();
} catch (Exception e) {
e.printStackTrace();
}
try {
// 获取响应body
in = new BufferedReader(new InputStreamReader(connection.getInputStream(), "UTF-8"));
String line;
while ((line = in.readLine()) != null) {
result += line;
}
in.close();
connection.disconnect();
} catch (Exception e) {
e.printStackTrace();
}
} catch (Exception e) {
e.printStackTrace();
//return null;
}
return result;
}
/**
* @param defURL
* @param token
* @return
* @throws Exception
*/
public String postByUrlAndToken(String defURL, String token, JSONObject body) throws Exception {
URL url = new URL(defURL);
// 打开和URL之间的连接
HttpURLConnection con = (HttpURLConnection) url.openConnection();
con.setRequestMethod("POST");//请求post方式
con.setUseCaches(false); // Post请求不能使用缓存
con.setDoInput(true);// 设置是否从HttpURLConnection输入,默认值为 true
con.setDoOutput(true);// 设置是否使用HttpURLConnection进行输出,默认值为 false
//设置header内的参数 connection.setRequestProperty("健, "值");
con.setRequestProperty("Content-Type", "application/json");
con.setRequestProperty("Accept", "*/*");
con.setRequestProperty("Authorization", "Bearer " + token);
// 建立实际的连接
con.connect();
// 得到请求的输出流对象
OutputStreamWriter writer = new OutputStreamWriter(con.getOutputStream(), "UTF-8");
writer.write(body.toString());
writer.flush();
// 获取服务端响应,通过输入流来读取URL的响应
InputStream is = con.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(is, "UTF-8"));
StringBuffer sbf = new StringBuffer();
String strRead = null;
while ((strRead = reader.readLine()) != null) {
sbf.append(strRead);
sbf.append("\r\n");
}
reader.close();
is.close();
// 关闭连接
con.disconnect();
return sbf.toString();
}