New JavaScript Property to support Content Security Policy (#1706)
* New JavaScript Property to support Content Security Policy
This commit is contained in:
Родитель
528bebae6b
Коммит
e2d030c3e6
|
@ -0,0 +1 @@
|
|||
Microsoft.ApplicationInsights.AspNetCore.JavaScriptSnippet.ScriptBody.get -> string
|
|
@ -0,0 +1 @@
|
|||
Microsoft.ApplicationInsights.AspNetCore.JavaScriptSnippet.ScriptBody.get -> string
|
|
@ -0,0 +1 @@
|
|||
Microsoft.ApplicationInsights.AspNetCore.JavaScriptSnippet.ScriptBody.get -> string
|
|
@ -0,0 +1 @@
|
|||
Microsoft.ApplicationInsights.AspNetCore.JavaScriptSnippet.ScriptBody.get -> string
|
|
@ -1,11 +1,10 @@
|
|||
# Changelog
|
||||
|
||||
## VNext
|
||||
|
||||
- [New: JavaScript Property to support Content Security Policy](https://github.com/microsoft/ApplicationInsights-dotnet/issues/1443)
|
||||
- [Fix: All perf counters stop being collected when any of faulty counters are specified to collect on Azure WebApps](https://github.com/microsoft/ApplicationInsights-dotnet/issues/1686)
|
||||
- [Fix: Some perf counters aren't collected when app is hosted on Azure WebApp](https://github.com/microsoft/ApplicationInsights-dotnet/issues/1685)
|
||||
|
||||
|
||||
## Version 2.14.0-beta2
|
||||
- [Fix: AspNetCore AddApplicationInsightsSettings() and MissingMethodException](https://github.com/microsoft/ApplicationInsights-dotnet/issues/1702)
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".Solution Items", ".Solutio
|
|||
ProjectSection(SolutionItems) = preProject
|
||||
build.cmd = build.cmd
|
||||
build.ps1 = build.ps1
|
||||
CHANGELOG.md = CHANGELOG.md
|
||||
..\CHANGELOG.md = ..\CHANGELOG.md
|
||||
Common.targets = Common.targets
|
||||
dirs.proj = dirs.proj
|
||||
NuGet.config = NuGet.config
|
||||
|
|
|
@ -14,6 +14,9 @@
|
|||
/// </summary>
|
||||
public class JavaScriptSnippet : IJavaScriptSnippet
|
||||
{
|
||||
private const string ScriptTagBegin = @"<script type=""text/javascript"">";
|
||||
private const string ScriptTagEnd = "</script>";
|
||||
|
||||
/// <summary>JavaScript snippet.</summary>
|
||||
private static readonly string Snippet = Resources.JavaScriptSnippet;
|
||||
|
||||
|
@ -24,12 +27,12 @@
|
|||
private readonly IHttpContextAccessor httpContextAccessor;
|
||||
|
||||
/// <summary>Configuration instance.</summary>
|
||||
private TelemetryConfiguration telemetryConfiguration;
|
||||
private readonly TelemetryConfiguration telemetryConfiguration;
|
||||
|
||||
/// <summary> Weather to print authenticated user tracking snippet.</summary>
|
||||
private bool enableAuthSnippet;
|
||||
private readonly bool enableAuthSnippet;
|
||||
|
||||
private JavaScriptEncoder encoder;
|
||||
private readonly JavaScriptEncoder encoder;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="JavaScriptSnippet"/> class.
|
||||
|
@ -52,54 +55,84 @@
|
|||
this.telemetryConfiguration = telemetryConfiguration;
|
||||
this.httpContextAccessor = httpContextAccessor;
|
||||
this.enableAuthSnippet = serviceOptions.Value.EnableAuthenticationTrackingJavaScript;
|
||||
this.encoder = (encoder == null) ? JavaScriptEncoder.Default : encoder;
|
||||
this.encoder = encoder ?? JavaScriptEncoder.Default;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a code snippet with instrumentation key initialized from TelemetryConfiguration.
|
||||
/// Gets the full JavaScript Snippet in HTML script tags with instrumentation key initialized from TelemetryConfiguration.
|
||||
/// </summary>
|
||||
/// <returns>JavaScript code snippet with instrumentation key or empty if instrumentation key was not set for the application.</returns>
|
||||
/// <remarks>This method will evaluate if Telemetry has been disabled in the config and if the instrumentation key was provided by either setting InstrumentationKey or ConnectionString.</remarks>
|
||||
/// <returns>JavaScript code snippet with instrumentation key or returns string.Empty if instrumentation key was not set for the application.</returns>
|
||||
public string FullScript
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!this.IsAvailable())
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
else
|
||||
{
|
||||
return string.Concat(ScriptTagBegin, this.ScriptBody, ScriptTagEnd);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the JavaScript Snippet body (without HTML script tags) with instrumentation key initialized from TelemetryConfiguration.
|
||||
/// </summary>
|
||||
/// <returns>JavaScript code snippet with instrumentation key or returns string.Empty if instrumentation key was not set for the application.</returns>
|
||||
public string ScriptBody
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!this.telemetryConfiguration.DisableTelemetry)
|
||||
// Config JS SDK
|
||||
string insertConfig;
|
||||
if (!string.IsNullOrEmpty(this.telemetryConfiguration.ConnectionString))
|
||||
{
|
||||
// Config JS SDK
|
||||
string insertConfig;
|
||||
if (!string.IsNullOrEmpty(this.telemetryConfiguration.ConnectionString))
|
||||
{
|
||||
insertConfig = string.Format(CultureInfo.InvariantCulture, "connectionString: '{0}'", this.telemetryConfiguration.ConnectionString);
|
||||
}
|
||||
else if (!string.IsNullOrEmpty(this.telemetryConfiguration.InstrumentationKey))
|
||||
{
|
||||
insertConfig = string.Format(CultureInfo.InvariantCulture, "instrumentationKey: '{0}'", this.telemetryConfiguration.InstrumentationKey);
|
||||
}
|
||||
else
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
// Auth Snippet (setAuthenticatedUserContext)
|
||||
string insertAuthUserContext = string.Empty;
|
||||
if (this.enableAuthSnippet)
|
||||
{
|
||||
IIdentity identity = this.httpContextAccessor?.HttpContext?.User?.Identity;
|
||||
if (identity != null && identity.IsAuthenticated)
|
||||
{
|
||||
string escapedUserName = this.encoder.Encode(identity.Name);
|
||||
insertAuthUserContext = string.Format(CultureInfo.InvariantCulture, AuthSnippet, escapedUserName);
|
||||
}
|
||||
}
|
||||
|
||||
// Return full snippet
|
||||
// Developer Note: If you recently updated the snippet and are now getting "FormatException: Input string was not in a correct format." you need to escape all the curly braces; '{' => '{{' and '}' => '}}'.
|
||||
return string.Format(CultureInfo.InvariantCulture, Snippet, insertConfig, insertAuthUserContext);
|
||||
insertConfig = string.Format(CultureInfo.InvariantCulture, "connectionString: '{0}'", this.telemetryConfiguration.ConnectionString);
|
||||
}
|
||||
else if (!string.IsNullOrEmpty(this.telemetryConfiguration.InstrumentationKey))
|
||||
{
|
||||
insertConfig = string.Format(CultureInfo.InvariantCulture, "instrumentationKey: '{0}'", this.telemetryConfiguration.InstrumentationKey);
|
||||
}
|
||||
else
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
// Auth Snippet (setAuthenticatedUserContext)
|
||||
string insertAuthUserContext = string.Empty;
|
||||
if (this.enableAuthSnippet)
|
||||
{
|
||||
IIdentity identity = this.httpContextAccessor?.HttpContext?.User?.Identity;
|
||||
if (identity != null && identity.IsAuthenticated)
|
||||
{
|
||||
string escapedUserName = this.encoder.Encode(identity.Name);
|
||||
insertAuthUserContext = string.Format(CultureInfo.InvariantCulture, AuthSnippet, escapedUserName);
|
||||
}
|
||||
}
|
||||
|
||||
// Return snippet
|
||||
// Developer Note: If you recently updated the snippet and are now getting "FormatException: Input string was not in a correct format." you need to escape all the curly braces; '{' => '{{' and '}' => '}}'.
|
||||
return string.Format(CultureInfo.InvariantCulture, Snippet, insertConfig, insertAuthUserContext);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determine if we have enough information to build a full script.
|
||||
/// </summary>
|
||||
/// <returns>Returns true if we can build the JavaScript snippet.</returns>
|
||||
private bool IsAvailable()
|
||||
{
|
||||
if (this.telemetryConfiguration.DisableTelemetry)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
return !(string.IsNullOrEmpty(this.telemetryConfiguration.ConnectionString)
|
||||
&& string.IsNullOrEmpty(this.telemetryConfiguration.InstrumentationKey));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -121,16 +121,13 @@
|
|||
<value>appInsights.setAuthenticatedUserContext("{0}");</value>
|
||||
</data>
|
||||
<data name="JavaScriptSnippet" xml:space="preserve">
|
||||
<value><script type="text/javascript">
|
||||
|
||||
var sdkInstance="appInsightsSDK";window[sdkInstance]="appInsights";var aiName=window[sdkInstance],aisdk=window[aiName]||function(e){{function n(e){{t[e]=function(){{var n=arguments;t.queue.push(function(){{t[e].apply(t,n)}})}}}}var t={{config:e}};t.initialize=!0;var i=document,a=window;setTimeout(function(){{var n=i.createElement("script");n.src=e.url||"https://az416426.vo.msecnd.net/scripts/b/ai.2.min.js",i.getElementsByTagName("script")[0].parentNode.appendChild(n)}});try{{t.cookie=i.cookie}}catch(e){{}}t.queue=[],t.version=2;for(var r=["Event","PageView","Exception","Trace","DependencyData","Metric","PageViewPerformance"];r.length;)n("track"+r.pop());n("startTrackPage"),n("stopTrackPage");var s="Track"+r[0];if(n("start"+s),n("stop"+s),n("addTelemetryInitializer"),n("setAuthenticatedUserContext"),n("clearAuthenticatedUserContext"),n("flush"),!(!0===e.disableExceptionTracking||e.extensionConfig&&e.extensionConfig.ApplicationInsightsAnalytics&&!0===e.extensionConfig.ApplicationInsightsAnalytics.disableExceptionTracking)){{n("_"+(r="onerror"));var o=a[r];a[r]=function(e,n,i,a,s){{var c=o&&o(e,n,i,a,s);return!0!==c&&t["_"+r]({{message:e,url:n,lineNumber:i,columnNumber:a,error:s}}),c}},e.autoExceptionInstrumented=!0}}return t}}(
|
||||
<value>var sdkInstance="appInsightsSDK";window[sdkInstance]="appInsights";var aiName=window[sdkInstance],aisdk=window[aiName]||function(e){{function n(e){{t[e]=function(){{var n=arguments;t.queue.push(function(){{t[e].apply(t,n)}})}}}}var t={{config:e}};t.initialize=!0;var i=document,a=window;setTimeout(function(){{var n=i.createElement("script");n.src=e.url||"https://az416426.vo.msecnd.net/scripts/b/ai.2.min.js",i.getElementsByTagName("script")[0].parentNode.appendChild(n)}});try{{t.cookie=i.cookie}}catch(e){{}}t.queue=[],t.version=2;for(var r=["Event","PageView","Exception","Trace","DependencyData","Metric","PageViewPerformance"];r.length;)n("track"+r.pop());n("startTrackPage"),n("stopTrackPage");var s="Track"+r[0];if(n("start"+s),n("stop"+s),n("addTelemetryInitializer"),n("setAuthenticatedUserContext"),n("clearAuthenticatedUserContext"),n("flush"),!(!0===e.disableExceptionTracking||e.extensionConfig&&e.extensionConfig.ApplicationInsightsAnalytics&&!0===e.extensionConfig.ApplicationInsightsAnalytics.disableExceptionTracking)){{n("_"+(r="onerror"));var o=a[r];a[r]=function(e,n,i,a,s){{var c=o&&o(e,n,i,a,s);return!0!==c&&t["_"+r]({{message:e,url:n,lineNumber:i,columnNumber:a,error:s}}),c}},e.autoExceptionInstrumented=!0}}return t}}(
|
||||
{{
|
||||
{0}
|
||||
}});
|
||||
|
||||
window[aiName]=aisdk,aisdk.queue&&0===aisdk.queue.length&&aisdk.trackPageView({{}});
|
||||
{1}
|
||||
|
||||
</script></value>
|
||||
</value>
|
||||
</data>
|
||||
</root>
|
Загрузка…
Ссылка в новой задаче