我是Angular 5的新手,我正在ASP.NET Core 2.1应用程序中使用它。我试图通过外部服务使用其API来实现身份验证,但我被LinkedIn API卡住了。这与Google或Facebook的API完全不同,因为Linkedin改变了他的方法,用JSON取代了JS API。我使用的是Oauth 2.0 nuget包,提供Linkedin的Oauth。我有一个问题,与重定向到LinkedIn API与登录页面。我在没有Angular的情况下用ASP.NET Core应用程序测试了同样的方法,它工作正常,所以问题出在Angular方面,或者可能是我的项目没有正确配置为使用Angular。
我在点击LinkedIn按钮时添加了操作:
<button><img class="button-linkedIn" (click)="OnLinkedInLoad()"
src="../../assets/images/linkedIn-register2.png"></button>
它在login组件中处理:
@Component({
moduleId: module.id,
selector: 'app-login',
templateUrl: './login.component.html',
styleUrls: ['./login.component.css']
})
export class LoginComponent implements OnInit {
ngOnInit() {
}
constructor(
private userSrv: UsersService) { }
OnLinkedInLoad() {
this.userSrv.loginUserLinkedIn().subscribe()
}
}
登录组件使用users.service组件发送请求(GET):
@Injectable()
export class UsersService {
constructor(private httpClient: HttpClient) { }
addUser(user: User) {
return this.httpClient.post('/api/Users', user);
}
loginUserLinkedIn(): Observable<any> {
return this.httpClient.get<any>('/api/Users/signInLinkedIn');
}
}
最后在UsersController中:
[Route("api/[controller]")]
[ApiController]
public class UsersController : ControllerBase
{
public UsersController(LoginTestContext context)
{
}
[HttpGet("signInLinkedIn")]
public async Task LinkedInSignInAsync()
{
await HttpContext.ChallengeAsync("linkedin", new AuthenticationProperties() { RedirectUri = "/" });
}
}
下面是我在启动时的配置:
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<LoginTestContext>(options =>
options.UseNpgsql(Configuration.GetConnectionString("LoginTestContext")));
services.AddAuthentication(options =>
{
options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
})
.AddCookie(
)
.AddLinkedIn("linkedin", options =>
{
options.ClientId = this.Configuration.GetValue<string>("linkedin:clientid");
options.ClientSecret = this.Configuration.GetValue<string>("linkedin:clientSecret");
});
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
services.AddSpaStaticFiles(configuration =>
{
configuration.RootPath = "ClientApp/dist";
});
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseBrowserLink();
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("Users/Error");
}
//app.UseHsts();
app.UseSpaStaticFiles();
app.UseStaticFiles();
app.UseAuthentication();
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Users}/{action=Index}/{id?}");
});
app.UseSpa(spa =>
{
// To learn more about options for serving an Angular SPA from ASP.NET Core,
// see https://go.microsoft.com/fwlink/?linkid=864501
spa.Options.SourcePath = "ClientApp";
if (env.IsDevelopment())
{
spa.UseAngularCliServer(npmScript: "start");
}
});
}
}
编辑:
在调试过程中,我注意到控制台中的一个错误,单击LinkedIn按钮后,出现错误日志:
Access to XMLHttpRequest at
'https://www.linkedin.com/oauth/v2/authorization?client_id=XXXXXXXXX&scope=r_liteprofile%20r_emailaddress&response_type=code&redirect_uri=http%3A%2F%2Flocalhost%3A44325%2Fsignin-linkedin&state=CfDJ8NjmD6pBjdpBuQvhUqQ7m6g41igeIumDrha6i0V2JZrOt1u6nweQ9cllyzBMFUj8F2dttqoYX7GYZs9wg-W4O2N8Y9XGPXUwkj5Ojl16sHlYHab93vT3jQEbSXuCQja-Fyths8Rw6YwId0-Ibg8sTeBK-IJSB6_VN16o7h9Nlw24M1Qo3ZRAR8Aq-Yp9DZSdLCVOfzz0yFkvkhy5cJ1OhC0'
(redirected from 'http://localhost:44325/api/Users/signInLinkedIn') from origin 'http://localhost:44325'
has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
我尝试了一些CORS策略的修复:
1)添加
services.AddCors();
配置到启动中的ConfigureServices方法,并
app.UseCors(builder => builder.AllowAnyMethod().AllowAnyHeader().AllowAnyOrigin());
2)向HTTPContext响应添加标头:
this.ControllerContext.HttpContext.Response.Headers.Add("Access-Control-Allow-Origin", "*");
3)调用loginUserLinkedIn时添加HttpHeaders
loginUserLinkedIn(): Observable<any> {
const headers = new HttpHeaders().append('Access-Control-Allow-Origin', ['*']);
return this.httpClient.get<any>('/api/Users/signInLinkedIn', { headers });
但是在这些修复之后,错误仍然发生。
如何在使用Angular的ASP.NET Core应用程序中正确设置CORS策略?
2条答案
按热度按时间2skhul331#
从MDN
跨域资源共享(CORS)是一种使用额外的HTTP头来告诉浏览器让在一个源(域)运行的Web应用程序有权访问来自不同源的服务器的选定资源的机制。
您尝试从localhost URL访问linkedin URL,这是一个 Cross-Origin 请求(从localhost到linkedin),您无法绕过此限制。
任何关于CORS的设置必须在LinkedIn网站上进行;- )
您希望通过c#代码通过 Authenticate Code flow(支持)验证用户身份,请参阅此Microsoft Linkedin doc
我不知道ChallengeAsync指令,但是,可能你必须将代码从
到
否则,我认为挑战是由客户端应用程序(与CORS错误)。
要知道正确的URL,您可以:
1.阅读Microsoft Linkedin文档,您可以在其中看到一个示例
1.您可以尝试Fiddler嗅探ChallengeAsync调用的URL并粘贴到
Response.Redirect
命令oyjwcjzk2#
这段代码在我的@Component中为我解决了这个问题
您提供的代码允许用户从Angular应用程序发出请求而不会收到CORS错误,因为它从浏览器窗口本身执行请求,而不是从Angular应用程序的代码中执行请求。
在onLinkedinLogin函数中,应用程序将window.location.href设置为LinkedIn授权URL。这会导致浏览器导航到该URL,直接从浏览器发起请求。这种方法绕过了浏览器强制执行的同源策略,这是CORS的底层机制。
由于请求是由浏览器直接发起的,因此浏览器将处理任何必要的CORS头和与服务器的协商。这允许请求继续而不会遇到CORS错误。
为了在这种情况下处理跨域请求,需要在服务器端进行适当的CORS配置。