рдкрд░рд┐рдЪрдп
рдореЗрд░реЗ рд╕рдорд░реНрдерд┐рдд рдкреНрд░реЛрдЬреЗрдХреНрдЯреНрд╕ рдореЗрдВ рд╕реЗ рдПрдХ рдиреЗ рд╣рд╛рд▓ рд╣реА рдореЗрдВ .NET рдлреНрд░реЗрдорд╡рд░реНрдХ 4.5 рд╕реЗред рдиреЗрдЯ рдХреЛрд░ рд╕реЗ рдорд╛рдЗрдЧреНрд░реЗрдЯ рд╣реЛрдиреЗ рдХреА рд╕рдВрднрд╛рд╡рдирд╛ рдХрд╛ рд╡рд┐рд╢реНрд▓реЗрд╖рдг рдХрд░рдиреЗ рдФрд░ рд╕рдВрдЪрд┐рдд рддрдХрдиреАрдХреА рдЛрдг рдХреА рдПрдХ рдмрдбрд╝реА рд░рд╛рд╢рд┐ рдХреЛ рдлрд┐рд░ рд╕реЗ рддреИрдпрд╛рд░ рдХрд░рдиреЗ рдФрд░ рд░реЗрдХрд┐рдВрдЧ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдХреЗ рдорд╛рдорд▓реЗ рдореЗрдВ рд╕рд╛рдордирд╛ рдХрд░рдиреЗ рдХрд╛ рдХрд╛рдо рдХрд┐рдпрд╛ред рдЪреБрдирд╛рд╡ рд▓рдХреНрд╖реНрдп рдкреНрд▓реЗрдЯрдлрд╝реЙрд░реНрдо .NET рдХреЛрд░ 3.0 рдкрд░ рдЧрд┐рд░ рдЧрдпрд╛, рдХреНрдпреЛрдВрдХрд┐, Microsoft рдХреЗ рдбреЗрд╡рд▓рдкрд░реНрд╕ рдХреЗ рдЕрдиреБрд╕рд╛рд░, рд╕рдВрд╕реНрдХрд░рдг 3.0 рдХреА рд░рд┐рд▓реАрдЬрд╝ рдХреЗ рд╕рд╛рде, рд╡рд┐рд░рд╛рд╕рдд рдХреЛрдб рдХреЛ рд╕реНрдерд╛рдирд╛рдВрддрд░рд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЖрд╡рд╢реНрдпрдХ рдХрджрдо рдХрдИ рдмрд╛рд░ рдХрдо рд╣реЛ рдЬрд╛рдПрдВрдЧреЗред рд╡рд┐рд╢реЗрд╖ рд░реВрдк рд╕реЗ рд╣рдо EntityFramework 6.3 for .Net Core рдпрд╛рдиреА рдХреЗ рд▓рд┐рдП рдирд┐рдХрд╛рд╕ рдпреЛрдЬрдирд╛рдУрдВ рджреНрд╡рд╛рд░рд╛ рдЗрд╕рдХреА рдУрд░ рдЖрдХрд░реНрд╖рд┐рдд рд╣реБрдП рдереЗ ред рд╢реБрджреНрдз рдХреЛрд░ рдкрд░ рдПрдХ рдорд╛рдЗрдЧреНрд░реЗрдЯреЗрдб рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдореЗрдВ EF 6.2 рдкрд░ рдЖрдзрд╛рд░рд┐рдд рдЕрдзрд┐рдХрд╛рдВрд╢ рдХреЛрдб "рдЬреИрд╕рд╛ рд╣реИ" рдЫреЛрдбрд╝рд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред
рдбреЗрдЯрд╛ рд╕реНрддрд░ рдХреЗ рд╕рд╛рде, рдРрд╕рд╛ рд▓рдЧрддрд╛ рд╣реИ, рдпрд╣ рд╕реНрдкрд╖реНрдЯ рд╣реЛ рдЧрдпрд╛, рд╣рд╛рд▓рд╛рдВрдХрд┐, рдХреЛрдб рдкреЛрд░реНрдЯрд┐рдВрдЧ рдХрд╛ рдПрдХ рдФрд░ рдмрдбрд╝рд╛ рд╣рд┐рд╕реНрд╕рд╛ рд╕реБрд░рдХреНрд╖рд╛ рдХрд╛ рд╕реНрддрд░ рдерд╛, рдЬреЛ рджреБрд░реНрднрд╛рдЧреНрдп рд╕реЗ, рдПрдХ рддреНрд╡рд░рд┐рдд рдСрдбрд┐рдЯ рдХреЗ рдмрд╛рдж, рдЖрдкрдХреЛ рд▓рдЧрднрдЧ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рдЗрд╕реЗ рдмрд╛рд╣рд░ рдлреЗрдВрдХрдирд╛ рд╣реЛрдЧрд╛ рдФрд░ рдЗрд╕реЗ рдЦрд░реЛрдВрдЪ рд╕реЗ рдлрд┐рд░ рд╕реЗ рд▓рд┐рдЦрдирд╛ рд╣реЛрдЧрд╛ред рд╕реМрднрд╛рдЧреНрдп рд╕реЗ, рдкрд░рд┐рдпреЛрдЬрдирд╛ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдПрдПрд╕рдкреА рдиреЗрдЯ рдЖрдЗрдбреЗрдВрдЯрд┐рдЯреА рдХреЗ рд╣рд┐рд╕реНрд╕реЗ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреА рдереА, рд╕реНрдЯреЛрд░рд┐рдВрдЧ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛рдУрдВ рдФрд░ рдЕрдиреНрдп "рд╕рд╛рдЗрдХрд┐рд▓" рдХреЗ рд░реВрдк рдореЗрдВред
рдпрд╣ рддрд╛рд░реНрдХрд┐рдХ рдкреНрд░рд╢реНрди рдЙрдард╛рддрд╛ рд╣реИ: рдпрджрд┐ рд╕реБрд░рдХреНрд╖рд╛ рднрд╛рдЧ рдореЗрдВ рдмрд╣реБрдд рдЕрдзрд┐рдХ рдкрд░рд┐рд╡рд░реНрддрди рдХрд░рдирд╛ рд╣реИ, рддреЛ рдЙрджреНрдпреЛрдЧ рдорд╛рдирдХреЛрдВ рдХреЗ рд░реВрдк рдореЗрдВ рдЕрдиреБрд╢рдВрд╕рд┐рдд рджреГрд╖реНрдЯрд┐рдХреЛрдгреЛрдВ рдХреЛ рддреБрд░рдВрдд рд▓рд╛рдЧреВ рдХреНрдпреЛрдВ рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдП, рдЕрд░реНрдерд╛рддреН: рдЖрдЗрдбреЗрдВрдЯрд┐рдЯреАрд╕реЗрд╡рд░ 4 рдврд╛рдВрдЪреЗ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдУрдкрди рдЖрдИрдбреА рдХрдиреЗрдХреНрдЯ рдФрд░ рдУрдЙрде рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдкреНрд▓рд┐рдХреЗрд╢рди рд▓рд╛рдПрдВред
рд╕рдорд╕реНрдпрд╛рдУрдВ рдФрд░ рд╕рдорд╛рдзрд╛рди
рддреЛ, рд╣рдореЗрдВ рджрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ: рдПрдВрдЧреБрд▓рд░ рдореЗрдВ рдПрдХ рдЬрд╛рд╡рд╛рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рд╣реИ (рдЖрдИрдПрд╕ 4 рд╢рдмреНрджреЛрдВ рдореЗрдВ рдХреНрд▓рд╛рдЗрдВрдЯ), рдпрд╣ рд╡реЗрдмрдПрдкреАрдЖрдИ (рд╕рдВрд╕рд╛рдзрди) рдХреЗ рдПрдХ рдирд┐рд╢реНрдЪрд┐рдд рд╕рдмрд╕реЗрдЯ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реИ, рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рд▓реЙрдЧрд┐рди рдХреЗ рд╕рд╛рде рдкреБрд░рд╛рдиреА рдПрдПрд╕рдкреА рдиреЗрдЯ рдкрд╣рдЪрд╛рди рдХрд╛ рдПрдХ рдбреЗрдЯрд╛рдмреЗрд╕ рднреА рд╣реИ рдЬрд┐рд╕реЗ рдЕрдкрдбреЗрдЯ рдХреЗ рдмрд╛рдж рдлрд┐рд░ рд╕реЗ рд╢реБрд░реВ рдХрд┐рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдП (рддрд╛рдХрд┐ рдЕрдиреНрдп рд╕рднреА рдХреЛ рд╢реБрд░реВ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдирд╣реАрдВред рд╕рдордп), рдкреНрд▓рд╕ рдХреБрдЫ рдорд╛рдорд▓реЛрдВ рдореЗрдВ рдЖрдЗрдбреЗрдВрдЯрд┐рдЯреАрд╕реЗрд╡рд░ 4 рдХреА рдУрд░ рд╕реЗ рд╡рд┐рдВрдбреЛрдЬ рдкреНрд░рдорд╛рдгреАрдХрд░рдг рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рд╕рд┐рд╕реНрдЯрдо рдореЗрдВ рд▓реЙрдЧ рдЗрди рдХрд░рдиреЗ рдХрд╛ рдЕрд╡рд╕рд░ рджреЗрдирд╛ рдЖрд╡рд╢реНрдпрдХ рд╣реИред рдпрд╛рдиреА рдРрд╕реЗ рд╕рдордп рд╣реЛрддреЗ рд╣реИрдВ рдЬрдм рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ ActiveDirectory рдбреЛрдореЗрди рдореЗрдВ рдПрдХ рд╕реНрдерд╛рдиреАрдп рдХреНрд╖реЗрддреНрд░ рдиреЗрдЯрд╡рд░реНрдХ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдХрд╛рдо рдХрд░рддреЗ рд╣реИрдВред
рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдбреЗрдЯрд╛ рдХреЛ рдорд╛рдЗрдЧреНрд░реЗрдЯ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдореБрдЦреНрдп рд╕рдорд╛рдзрд╛рди рдореИрдиреНрдпреБрдЕрд▓ рд░реВрдк рд╕реЗ (рдпрд╛ рд╕реНрд╡рдЪрд╛рд▓рд┐рдд рдЯреВрд▓ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ) рдкреБрд░рд╛рдиреЗ рдФрд░ рдирдП рдЖрдЗрдбреЗрдВрдЯрд┐рдЯреА рд╕реНрдХреАрдорд╛ рдХреЗ рдмреАрдЪ рдПрдХ рдорд╛рдЗрдЧреНрд░реЗрд╢рди рд╕реНрдХреНрд░рд┐рдкреНрдЯ рд▓рд┐рдЦрдирд╛ рд╣реИред рд╣рдо, рдмрджрд▓реЗ рдореЗрдВ, рд╕реНрд╡рдЪрд╛рд▓рд┐рдд рдбреЗрдЯрд╛ рд╕реНрдХреАрдорд╛ рддреБрд▓рдирд╛ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВ рдФрд░ рдПрдХ рдПрд╕рдХреНрдпреВрдПрд▓ рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдЙрддреНрдкрдиреНрди рдХрд░рддреЗ рд╣реИрдВ, рдкрд╣рдЪрд╛рди рд╕рдВрд╕реНрдХрд░рдг рдХреЗ рдЖрдзрд╛рд░ рдкрд░, рд▓рдХреНрд╖реНрдп рдорд╛рдЗрдЧреНрд░реЗрд╢рди рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдореЗрдВ рдЕрд▓рдЧ-рдЕрд▓рдЧ рдЕрдкрдбреЗрдЯ рдирд┐рд░реНрджреЗрд╢ рд╣реЛрдВрдЧреЗред рдпрд╣рд╛рдБ рдореБрдЦреНрдп рдмрд╛рдд рдпрд╣ рд╣реИ рдХрд┐ EFMigrationsHistory рдЯреЗрдмрд▓ рдХрд╛ рд╕рдордиреНрд╡рдп рдХрд░рдирд╛ рди рднреВрд▓реЗрдВ рдпрджрд┐ EF рдХрд╛ рдЙрдкрдпреЛрдЧ рдкрд╣рд▓реЗ рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛ рдФрд░ рднрд╡рд┐рд╖реНрдп рдореЗрдВ рдЗрд╕рдХреА рдпреЛрдЬрдирд╛ рдмрдирд╛рдИ рдЧрдИ рд╣реИ, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, IdentityUser рдЗрдХрд╛рдИ рдХреЛ рдЕрддрд┐рд░рд┐рдХреНрдд рдХреНрд╖реЗрддреНрд░реЛрдВ рдореЗрдВ рд╡рд┐рд╕реНрддрд╛рд░рд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдПред
рд▓реЗрдХрд┐рди рдЕрдм IdentityServer4 рдХреЛ рд╕рд╣реА рдврдВрдЧ рд╕реЗ рдХреИрд╕реЗ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░ рдХрд░реЗрдВ рдФрд░ рдЗрд╕реЗ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░ рдХрд░реЗрдВ рд╡рд┐рдВрдбреЛрдЬ рдЦрд╛рддреЛрдВ рдХреЗ рд╕рд╛рде рдиреАрдЪреЗ рд╡рд░реНрдгрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ред
рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдпреЛрдЬрдирд╛
NDA рдХрд╛рд░рдгреЛрдВ рд╕реЗ, рдореИрдВрдиреЗ рдпрд╣ рд╡рд░реНрдгрди рдирд╣реАрдВ рдХрд┐рдпрд╛ рдХрд┐ рд╣рдо рдЕрдкрдиреА рдкрд░рд┐рдпреЛрдЬрдирд╛ рдореЗрдВ IS4 рдХреЛ рдХреИрд╕реЗ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рд┐рдд рдХрд░рдиреЗ рдореЗрдВ рдХрд╛рдордпрд╛рдм рд░рд╣реЗ, рд╣рд╛рд▓рд╛рдБрдХрд┐, рдЗрд╕ рд▓реЗрдЦ рдореЗрдВ, рдореИрдВ рдЖрдкрдХреЛ рдПрдХ рд╕рд░рд▓ ASP.NET рдХреЛрд░ рд╕рд╛рдЗрдЯ рдкрд░ рджрд┐рдЦрд╛рдКрдБрдЧрд╛ рдЬреЛ рдХрд┐ рд╕реНрдХреНрд░реИрдЪ рд╕реЗ рдмрдирд╛рдИ рдЧрдИ рд╣реИ рдЬрд┐рд╕реЗ рдЖрдкрдХреЛ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░ рдФрд░ рдХрд╛рд░реНрдпрд╛рддреНрдордХ рдЕрдиреБрдкреНрд░рдпреЛрдЧ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХреНрдпрд╛ рдХрджрдо рдЙрдард╛рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рдкреНрд░рд╛рдзрд┐рдХрд░рдг рдФрд░ рдкреНрд░рдорд╛рдгреАрдХрд░рдг рдЙрджреНрджреЗрд╢реНрдпреЛрдВ рдХреЗ рд▓рд┐рдП IdentityServer4 рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реИред
рд╡рд╛рдВрдЫрд┐рдд рд╡реНрдпрд╡рд╣рд╛рд░ рдХрд╛ рдПрд╣рд╕рд╛рд╕ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдореЗрдВ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдХрджрдо рдЙрдард╛рдиреЗ рд╣реЛрдВрдЧреЗ:
- рдПрдХ рд░рд┐рдХреНрдд ASP.Net рдХреЛрд░ рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдмрдирд╛рдПрдБ рдФрд░ IdentityServer4 рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХреЙрдиреНрдлрд╝рд┐рдЧрд░ рдХрд░реЗрдВред
- рдПрдХ рдХреНрд▓рд╛рдЗрдВрдЯ рдХреЛ рдХреЛрдгреАрдп рдЕрдиреБрдкреНрд░рдпреЛрдЧ рдХреЗ рд░реВрдк рдореЗрдВ рдЬреЛрдбрд╝реЗрдВред
- рдУрдкрди-рдЖрдИрдбреА-рдХрдиреЗрдХреНрдЯ рдЧреВрдЧрд▓ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рд▓реЙрдЧ рдЗрди рдХрд░реЗрдВ
- Windows рдкреНрд░рдорд╛рдгреАрдХрд░рдг рд╡рд┐рдХрд▓реНрдк рдЬреЛрдбрд╝реЗрдВ
рд╕рдВрдХреНрд╖рд┐рдкреНрддрддрд╛ рдХрд╛рд░рдгреЛрдВ рдХреЗ рд▓рд┐рдП, рд╕рднреА рддреАрди рдШрдЯрдХ (IdentityServer, WebAPI, рдХреЛрдгреАрдп рдЧреНрд░рд╛рд╣рдХ) рдПрдХ рд╣реА рдкрд░рд┐рдпреЛрдЬрдирд╛ рдореЗрдВ рд╣реЛрдВрдЧреЗред рдХреНрд▓рд╛рдЗрдВрдЯ рдФрд░ рдЖрдЗрдбреЗрдВрдЯрд┐рдЯреА рд╕реЗрд╡рд░ (рдЧреНрд░рд╛рдВрдЯ рдЯрд╛рдЗрдк) рдХреЗ рдмреАрдЪ рдЪрдпрдирд┐рдд рдкреНрд░рдХрд╛рд░ рдХрд╛ рдЗрдВрдЯрд░реИрдХреНрд╢рди рдЗрдореНрдкреНрд▓рд┐рдХреНрдЯ рдлреНрд▓реЛ рд╣реИ, рдЬрдм рдПрдХреНрд╕реЗрд╕_рдЯреЛрдХрди рдХреЛ рдмреНрд░рд╛рдЙрдЬрд╝рд░ рдореЗрдВ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рд╕рд╛рдЗрдб рдореЗрдВ рдкрд╛рд╕ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдФрд░ рддрдм рд╡реЗрдмрдПрдкреАрдЖрдИ рдХреЗ рд╕рд╛рде рдЗрдВрдЯрд░реИрдХреНрдЯ рдХрд░рддреЗ рд╕рдордп рдЗрд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред ASP.NET рдХреЛрд░ рд░рд┐рдкреЙрдЬрд┐рдЯрд░реА рдореЗрдВ рд╣реБрдП рдмрджрд▓рд╛рд╡реЛрдВ рдХреЛ рджреЗрдЦрддреЗ рд╣реБрдП рдХреНрд▓реЛрдЬрд╝рд░ рдХреЛ рд░рд┐рд▓реАрдЬрд╝ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдЗрдореНрдкреНрд▓рд┐рдХреНрдЯ рдлреНрд▓реЛ рдХреЛ рдкреНрд░рд╛рдзрд┐рдХрд░рдг рдХреЛрдб + PKCE рджреНрд╡рд╛рд░рд╛ рдмрджрд▓ рджрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ред)
рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдХреЛ рдмрдирд╛рдиреЗ рдФрд░ рд╕рдВрд╢реЛрдзрд┐рдд рдХрд░рдиреЗ рдХреА рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдореЗрдВ, .NET рдХреЛрд░ рдХрдорд╛рдВрдб рд▓рд╛рдЗрди рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдХрд╛ рд╡реНрдпрд╛рдкрдХ рд░реВрдк рд╕реЗ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛, рдЗрд╕реЗ рд╕рд┐рд╕реНрдЯрдо рдореЗрдВ рдкреНрд░реАрд╡реНрдпреВ рдХреЛрд░ 3.0 рдХреЗ рдирд╡реАрдирддрдо рд╕рдВрд╕реНрдХрд░рдг (рдЖрд░реНрдЯрд┐рдХрд▓ рд▓рд┐рдЦрдиреЗ рдХреЗ рд╕рдордп 3.0.100-рдкреНрд░реАрд╡реНрдпреВ 7-012821) рдХреЗ рд╕рд╛рде рд╕реНрдерд╛рдкрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдПред
рдПрдХ рд╡реЗрдм рдкрд░рд┐рдпреЛрдЬрдирд╛ рдХрд╛ рдирд┐рд░реНрдорд╛рдг рдФрд░ рд╡рд┐рдиреНрдпрд╛рд╕
IdentityServer рд╕рдВрд╕реНрдХрд░рдг 4 рдХреА рд░рд┐рд▓реАрдЬ рдЗрд╕ рдврд╛рдВрдЪреЗ рд╕реЗ рдпреВрдЖрдИ рдХреЗ рдкреВрд░реНрдг рдХрдЯрд┐рдВрдЧ рджреНрд╡рд╛рд░рд╛ рдЪрд┐рд╣реНрдирд┐рдд рдХреА рдЧрдИ рдереАред рдЕрдм рдбреЗрд╡рд▓рдкрд░реНрд╕ рдХреЛ рдкреНрд░рд╛рдзрд┐рдХрд░рдг рд╕рд░реНрд╡рд░ рдХреЗ рдореБрдЦреНрдп рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдХреЛ рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХрд░рдиреЗ рдХрд╛ рдкреВрд░реНрдг рдЕрдзрд┐рдХрд╛рд░ рд╣реИред рдЗрд╕рдХреЗ рдХрдИ рддрд░реАрдХреЗ рд╣реИрдВред рд▓реЛрдХрдкреНрд░рд┐рдп рд▓реЛрдЧреЛрдВ рдореЗрдВ рд╕реЗ рдПрдХ QuickStart UI рдкреИрдХреЗрдЬ рд╕реЗ UI рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рд╣реИ, рдЬрд┐рд╕реЗ рдЬреАрдердм рдкрд░ рдЖрдзрд┐рдХрд╛рд░рд┐рдХ рд░рд┐рдкреЙрдЬрд┐рдЯрд░реА рдореЗрдВ рдкрд╛рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред
рджреВрд╕рд░рд╛, рдХреЛрдИ рдХрдо рд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ рдирд╣реАрдВ рд╣реИ, рдПрдПрд╕рдкреА рдиреЗрдЯ рдХреЛрд░ рдЖрдЗрдбреЗрдВрдЯрд┐рдЯреА рдпреВрдЖрдИ рдХреЗ рд╕рд╛рде рдПрдХреАрдХрд░рдг рд╣реИ, рдЗрд╕ рдорд╛рдорд▓реЗ рдореЗрдВ, рдбреЗрд╡рд▓рдкрд░ рдХреЛ рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдореЗрдВ рд╕рдВрдмрдВрдзрд┐рдд рдорд┐рдбрд▓рд╡реЗрдпрд░ рдХреЛ рд╕рд╣реА рдврдВрдЧ рд╕реЗ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рдЗрд╕ рд╡рд┐рдзрд┐ рдХрд╛ рд╡рд░реНрдгрди рдмрд╛рдж рдореЗрдВ рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ред
рдЖрдЗрдП рдПрдХ рд╕рд░рд▓ рд╡реЗрдм рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдмрдирд╛рдХрд░ рд╢реБрд░реВ рдХрд░реЗрдВред рдРрд╕рд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдХрдорд╛рдВрдб рд▓рд╛рдЗрди рдкрд░ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдирд┐рд░реНрджреЗрд╢ рдХреЛ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд░реЗрдВ:
dotnet new webapp -n IdentityServer4WebApp
рдирд┐рд╖реНрдкрд╛рджрди рдХреЗ рдмрд╛рдж, рдЖрдЙрдЯрдкреБрдЯ рдПрдХ рд╡реЗрдм рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдлреНрд░реЗрдорд╡рд░реНрдХ рд╣реЛрдЧрд╛, рдЬрд┐рд╕реЗ рдзреАрд░реЗ-рдзреАрд░реЗ рдЙрд╕ рд░рд╛рдЬреНрдп рдореЗрдВ рд▓рд╛рдпрд╛ рдЬрд╛рдПрдЧрд╛ рдЬрд┐рд╕рдХреА рд╣рдореЗрдВ рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рдпрд╣рд╛рдВ рдЖрдкрдХреЛ рдПрдХ рдЖрд░рдХреНрд╖рдг рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ рдЬреЛ рдкрд╣рдЪрд╛рди рдХреЗ рд▓рд┐рдП .Net рдХреЛрд░ 3.0 рд╣реИрд╡реАрд╡реЗрдЯ рдПрдорд╡реАрд╕реА рдХреЗ рд╡рд┐рдкрд░реАрдд, рдЕрдзрд┐рдХ рд╣рд▓реНрдХреЗ рд░реЗрдЬрд╝рд░рдкреЗрдЬ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реИред
рдЕрдм рдЖрдкрдХреЛ рд╣рдорд╛рд░реЗ рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдореЗрдВ IdentityServer рд╕рдорд░реНрдерди рдЬреЛрдбрд╝рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рдРрд╕рд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдЖрд╡рд╢реНрдпрдХ рдкреИрдХреЗрдЬ рд╕реНрдерд╛рдкрд┐рдд рдХрд░реЗрдВ:
dotnet add package Microsoft.AspNetCore.ApiAuthorization.IdentityServer -v 3.0.0-preview7.19365.7 dotnet add package Microsoft.AspNetCore.Identity.EntityFrameworkCore -v 3.0.0-preview7.19365.7 dotnet add package Microsoft.EntityFrameworkCore.Tools -v 3.0.0-preview7.19362.6 dotnet add package Microsoft.EntityFrameworkCore.Sqlite -v 3.0.0-preview7.19362.6
рдкреНрд░рд╛рдзрд┐рдХрд░рдг рд╕рд░реНрд╡рд░ рдкреИрдХреЗрдЬреЛрдВ рдХреЗ рд▓рд┐рдВрдХ рдХреЗ рдЕрд▓рд╛рд╡рд╛, рдпрд╣рд╛рдВ рд╣рдордиреЗ рдкрд╣рдЪрд╛рди рдкрд╛рд░рд┐рд╕реНрдерд┐рддрд┐рдХреА рддрдВрддреНрд░ рдореЗрдВ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдЬрд╛рдирдХрд╛рд░реА рд╕рдВрдЧреНрд░рд╣реАрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдВрдЯрд┐рдЯреА рдлреНрд░реЗрдорд╡рд░реНрдХ рд╕рдорд░реНрдерди рдЬреЛрдбрд╝рд╛ рд╣реИред рд╕рд░рд▓рддрд╛ рдХреЗ рд▓рд┐рдП, рд╣рдо SQLite рдбреЗрдЯрд╛рдмреЗрд╕ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВрдЧреЗред
рдбреЗрдЯрд╛рдмреЗрд╕ рдХреЛ рдЗрдирд┐рд╢рд┐рдпрд▓рд╛рдЗрдЬрд╝ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдЕрдкрдирд╛ рдпреВрдЬрд░ рдореЙрдбрд▓ рдФрд░ рдбреЗрдЯрд╛рдмреЗрд╕ рд╕рдВрджрд░реНрдн рдмрдирд╛рдПрдБ, рдЗрд╕рдХреЗ рд▓рд┐рдП рд╣рдо рджреЛ ApplicationUser рдХреНрд▓рд╛рд╕реЗрд╕ рдХреА рдШреЛрд╖рдгрд╛ рдХрд░рддреЗ рд╣реИрдВ, рдЬрд┐рдиреНрд╣реЗрдВ рдореЙрдбрд▓ рдлрд╝реЛрд▓реНрдбрд░ рдореЗрдВ IdentityUser рд╕реЗ рд╡рд┐рд░рд╛рд╕рдд рдореЗрдВ рдорд┐рд▓рд╛ рд╣реИ рдФрд░ ApplicationDbContext , рдЗрдирд╕реЗ рд╡рд┐рд░рд╛рд╕рдд рдореЗрдВ рдорд┐рд▓рд╛ рд╣реИ: рдбреЗрдЯрд╛ рдлрд╝реЛрд▓реНрдбрд░ рдореЗрдВ ApiAuthorizationDonContextред
рдЕрдЧрд▓рд╛, рдЖрдкрдХреЛ EntityFramework рд╕рдВрджрд░реНрдн рдХреЗ рдЙрдкрдпреЛрдЧ рдХреЛ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░ рдХрд░рдиреЗ рдФрд░ рдбреЗрдЯрд╛рдмреЗрд╕ рдмрдирд╛рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рдРрд╕рд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдо рд╕рдВрджрд░реНрдн рдХреЛ рд╕реНрдЯрд╛рд░реНрдЯрдЕрдк рдХреНрд▓рд╛рд╕ рдХреЗ рдХреЙрдиреНрдлрд┐рдЧрд░рд╕реНрд╡рд╛рдЗрд╕ рд╡рд┐рдзрд┐ рдореЗрдВ рд▓рд┐рдЦрддреЗ рд╣реИрдВ:
public void ConfigureServices(IServiceCollection services) { services.AddDbContext<ApplicationDbContext>(options =>options.UseSqlite(Configuration.GetConnectionString("DefaultConnection"))); services.AddRazorPages(); }
рдФрд░ appstings.json рдХреЗ рд▓рд┐рдП рдХрдиреЗрдХреНрд╢рди рд╕реНрдЯреНрд░рд┐рдВрдЧ рдЬреЛрдбрд╝реЗрдВ
"ConnectionStrings": { "DefaultConnection": "Data Source=data.db" },
рдЕрдм рдЖрдк рдкреНрд░рд╛рд░рдВрднрд┐рдХ рдорд╛рдЗрдЧреНрд░реЗрд╢рди рдмрдирд╛ рд╕рдХрддреЗ рд╣реИрдВ рдФрд░ рдбреЗрдЯрд╛рдмреЗрд╕ рд╕реНрдХреАрдорд╛ рдХреЛ рдЗрдирд┐рд╢рд┐рдпрд▓рд╛рдЗрдЬрд╝ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рдпрд╣ рдзреНрдпрд╛рди рджреЗрдиреЗ рдпреЛрдЧреНрдп рд╣реИ рдХрд┐ рдПрдлрдИ рдХреЛрд░ рдХреЗ рд▓рд┐рдП рд╕реНрдерд╛рдкрд┐рдд рдЯреВрд▓ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ (рдкреНрд░рд╢реНрди рдореЗрдВ рдкреВрд░реНрд╡рд╛рд╡рд▓реЛрдХрди рдХреЗ рд▓рд┐рдП, рд╕рдВрд╕реНрдХрд░рдг 3.0.0-рдкреВрд░реНрд╡рд╛рд╡рд▓реЛрдХрди 7.19362.6 рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ)ред
dotnet ef migrations add Init dotnet ef database update
рдпрджрд┐ рдкрд┐рдЫрд▓реЗ рд╕рднреА рдЪрд░рдг рддреНрд░реБрдЯрд┐рдпреЛрдВ рдХреЗ рдмрд┐рдирд╛ рдкреВрд░реЗ рд╣реЛ рдЧрдП рдереЗ, рддреЛ SQLite рдбреЗрдЯрд╛ рдлрд╝рд╛рдЗрд▓ data.db рдЖрдкрдХреЗ рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдореЗрдВ рджрд┐рдЦрд╛рдИ рджреЗрдиреА рдЪрд╛рд╣рд┐рдПред
рдЗрд╕ рд╕реНрддрд░ рдкрд░, рд╣рдо рдкреВрд░реА рддрд░рд╣ рд╕реЗ Asp.Net рдХреЛрд░ рдкрд╣рдЪрд╛рди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреА рдкреВрд░реНрдг рдХреНрд╖рдорддрд╛ рдХреЛ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░ рдФрд░ рдкрд░реАрдХреНрд╖рдг рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рдРрд╕рд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╕реНрдЯрд╛рд░реНрдЯрдЕрдк рд╡рд┐рдзрд┐рдпреЛрдВ рдореЗрдВ рдкрд░рд┐рд╡рд░реНрддрди рдХрд░реЗрдВ ред рдХреЙрдиреНрдлрд╝рд┐рдЧрд░ рдХрд░реЗрдВ рдФрд░ Start.ConfigureServices ред
рдЗрди рдкрдВрдХреНрддрд┐рдпреЛрдВ рдХреЗ рд╕рд╛рде, рд╣рдо рдЕрдиреБрд░реЛрдз рдкреНрд░рд╕рдВрд╕реНрдХрд░рдг рдкрд╛рдЗрдкрд▓рд╛рдЗрди рдореЗрдВ рдкреНрд░рдорд╛рдгреАрдХрд░рдг рдФрд░ рдкреНрд░рд╛рдзрд┐рдХрд░рдг рдХреА рд╕рдВрднрд╛рд╡рдирд╛ рдХреЛ рдПрдореНрдмреЗрдб рдХрд░рддреЗ рд╣реИрдВред рдФрд░ рдкрд╣рдЪрд╛рди рдХреЗ рд▓рд┐рдП рдбрд┐рдлрд╝реЙрд▓реНрдЯ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рднреА рдЬреЛрдбрд╝реЗрдВред
рдпрд╣ рдХреЗрд╡рд▓ рдпреВрдЖрдИ рдХреЛ рдареАрдХ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдмрдиреА рд╣реБрдИ рд╣реИ, \ _ogogPartial.cshtml рдирд╛рдо рдФрд░ рдирд┐рдореНрди рд╕рд╛рдордЧреНрд░реА рдХреЗ рд╕рд╛рде рдПрдХ рдирдпрд╛ рд░реЗрдЬрд░ рджреЗрдЦреЗрдВ
@using IdentityServer4WebApp.Models @using Microsoft.AspNetCore.Identity @inject SignInManager<ApplicationUser> SignInManager @inject UserManager<ApplicationUser> UserManager <ul class="navbar-nav"> @if (SignInManager.IsSignedIn(User)) { <li class="nav-item"> <a class="nav-link text-dark" asp-area="Identity" asp-page="/Account/Manage/Index" title="Manage">Hello @User.Identity.Name!</a> </li> <li class="nav-item"> <form class="form-inline" asp-area="Identity" asp-page="/Account/Logout" asp-route-returnUrl="/"> <button type="submit" class="nav-link btn btn-link text-dark">Logout</button> </form> </li> } else { <li class="nav-item"> <a class="nav-link text-dark" asp-area="Identity" asp-page="/Account/Register">Register</a> </li> <li class="nav-item"> <a class="nav-link text-dark" asp-area="Identity" asp-page="/Account/Login">Login</a> </li> } </ul>
рдЙрдкрд░реНрдпреБрдХреНрдд рдкреНрд░рд╕реНрддреБрддрд┐ рдХреЛрдб рдХреЛ рдиреЗрд╡рд┐рдЧреЗрд╢рди рдкреИрдирд▓ (рдЕрдВрддрд░реНрдирд┐рд╣рд┐рдд рд▓реЙрдЧрд┐рди рдФрд░ рдкрд╛рд╕рд╡рд░реНрдб, рдкрдВрдЬреАрдХрд░рдг, рдЖрджрд┐) рдореЗрдВ рдЕрдВрддрд░реНрдирд┐рд╣рд┐рдд рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдирд┐рдпрдВрддреНрд░рдг рдХреЗ рд╕рд╛рде рдкрд╣рдЪрд╛рди рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдХреНрд╖реЗрддреНрд░ рд╕реЗ рд▓рд┐рдВрдХ рдЬреЛрдбрд╝рдирд╛ рдЪрд╛рд╣рд┐рдПред
рдирдП рдореЗрдиреВ рдЖрдЗрдЯрдореЛрдВ рдХреЗ рдкреНрд░рддрд┐рдкрд╛рджрди рдХреЛ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдо рдЗрд╕ рдЖрдВрд╢рд┐рдХ рджреГрд╢реНрдп рдХреЗ рдкреНрд░рддрд┐рдкрд╛рджрди рдХреЛ рдЬреЛрдбрд╝рдХрд░ _Layout.cshtml рдлрд╝рд╛рдЗрд▓ рдХреЛ рд╕рдВрд╢реЛрдзрд┐рдд рдХрд░рддреЗ рд╣реИрдВред
<ul class="navbar-nav flex-grow-1"> <li class="nav-item"> <a class="nav-link text-dark" asp-area="" asp-page="/Index">Home</a> </li> <li class="nav-item"> <a class="nav-link text-dark" asp-area="" asp-page="/Privacy">Privacy</a> </li> </ul> </div> <partial name="_LoginPartial" /> <!тАУтАУтАУтАУ> </div>
рдФрд░ рдЕрдм рдЪрд▓реЛ рд╣рдорд╛рд░реЗ рдЖрд╡реЗрджрди рдХреЛ рдЪрд▓рд╛рдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░рддреЗ рд╣реИрдВ рдФрд░ рдЙрди рд▓рд┐рдВрдХ рдкрд░ рдХреНрд▓рд┐рдХ рдХрд░рддреЗ рд╣реИрдВ рдЬреЛ рд╕рд┐рд░ рдореЗрдВ рджрд┐рдЦрд╛рдИ рджреЗрддреЗ рд╣реИрдВ
рдореЗрдиреВ, рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХреЛ рд╕реНрд╡рд╛рдЧрдд рдФрд░ рдЕрдиреБрд░реЛрдз рдХреЗ рд╕рд╛рде рдПрдХ рдкреГрд╖реНрда рджреЗрдЦрдирд╛ рдЪрд╛рд╣рд┐рдП
рд▓реЙрдЧрд┐рди рдФрд░ рдкрд╛рд╕рд╡рд░реНрдб рджрд░реНрдЬ рдХрд░реЗрдВред рдЗрд╕ рд╕реНрдерд┐рддрд┐ рдореЗрдВ, рдЖрдк рдкрдВрдЬреАрдХрд░рдг рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдФрд░ рд▓реЙрдЧ рдЗрди рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ - рд╕рднреА
рдХрд╛рдо рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдПред

IdentityServer4 рдбреЗрд╡рд▓рдкрд░реНрд╕ рдиреЗ ASP.NET рдЖрдЗрдбреЗрдВрдЯрд┐рдЯреА рдФрд░ рд╕рд░реНрд╡рд░ рдлреНрд░реЗрдорд╡рд░реНрдХ рдХреЗ рдПрдХреАрдХрд░рдг рдХреЛ рдмреЗрд╣рддрд░ рдмрдирд╛рдиреЗ рдХрд╛ рдПрдХ рдЙрддреНрдХреГрд╖реНрдЯ рдХрд╛рдо рдХрд┐рдпрд╛ рд╣реИред OAuth2 рдЯреЛрдХрди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреА рдХреНрд╖рдорддрд╛ рдЬреЛрдбрд╝рдиреЗ рдХреЗ рд▓рд┐рдП, рдЖрдкрдХреЛ рдХреЛрдб рдореЗрдВ рдХреБрдЫ рдирдП рдирд┐рд░реНрджреЗрд╢реЛрдВ рдХреЗ рд╕рд╛рде рд╣рдорд╛рд░реА рдкрд░рд┐рдпреЛрдЬрдирд╛ рдХреЛ рдкреВрд░рдХ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред
Startup.ConfigureServices рд╡рд┐рдзрд┐ рдХреА рдкрд╛рд░рдВрдЧрдд рд░реЗрдЦрд╛ рдореЗрдВ , ASP.NET рдХреЛрд░ рдкрд╣рдЪрд╛рди рдкрд░ IS4 рд╕рдореНрдореЗрд▓рдиреЛрдВ рдХрд╛ рд╡рд┐рдиреНрдпрд╛рд╕ рдЬреЛрдбрд╝реЗрдВ:
services.AddIdentityServer() .AddApiAuthorization<ApplicationUser, ApplicationDbContext>();
AddApiAuthorization рдкрджреНрдзрддрд┐ рдПрдХ рд╡рд┐рд╢рд┐рд╖реНрдЯ рд╕рдорд░реНрдерд┐рдд рдХреЙрдиреНрдлрд╝рд┐рдЧрд░реЗрд╢рди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдореБрдЦреНрдп рд░реВрдк рд╕реЗ appsettings.json рдлрд╝рд╛рдЗрд▓ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рд░реВрдкрд░реЗрдЦрд╛ рдХрд╛ рдирд┐рд░реНрджреЗрд╢ рджреЗрддреА рд╣реИред рдлрд┐рд▓рд╣рд╛рд▓, рдЕрдВрддрд░реНрдирд┐рд╣рд┐рдд IS4 рдкреНрд░рдмрдВрдзрди рдХреНрд╖рдорддрд╛рдПрдВ рдЗрддрдиреА рд▓рдЪреАрд▓реА рдирд╣реАрдВ рд╣реИрдВ рдФрд░ рдЗрд╕реЗ рдЖрдкрдХреЗ рдЕрдиреБрдкреНрд░рдпреЛрдЧреЛрдВ рдХреЗ рдирд┐рд░реНрдорд╛рдг рдХреЗ рд▓рд┐рдП рдПрдХ рдкреНрд░рд╛рд░рдВрднрд┐рдХ рдмрд┐рдВрджреБ рдорд╛рдирд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдПред рдХрд┐рд╕реА рднреА рд╕реНрдерд┐рддрд┐ рдореЗрдВ, рдЖрдк рдЗрд╕ рдкрджреНрдзрддрд┐ рдХреЗ рдЕрддрд┐рднрд╛рд░рд┐рдд рд╕рдВрд╕реНрдХрд░рдг рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдФрд░ рдХреЙрд▓рдмреИрдХ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдорд╛рдкрджрдВрдбреЛрдВ рдХреЛ рдЕрдзрд┐рдХ рд╡рд┐рд╕реНрддрд╛рд░ рд╕реЗ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред
рдЕрдЧрд▓рд╛, рд╣рдо рд╕рд╣рд╛рдпрдХ рд╡рд┐рдзрд┐ рдХреЛ рдХрд╣рддреЗ рд╣реИрдВ, рдЬреЛ рдлреНрд░реЗрдорд╡рд░реНрдХ рджреНрд╡рд╛рд░рд╛ рдЬрд╛рд░реА рдХрд┐рдП рдЧрдП рдЬреЗрдбрдмреНрд▓реНрдпреВрдЯреА рдЯреЛрдХрди рдХреА рдЬрд╛рдВрдЪ рдХреЗ рд▓рд┐рдП рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдХреЛ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░ рдХрд░рддрд╛ рд╣реИред
services.AddAuthentication() .AddIdentityServerJwt();
рдЕрдВрдд рдореЗрдВ, Start..Configure рд╡рд┐рдзрд┐ рдореЗрдВ , рдХреЗ рд▓рд┐рдП рдорд┐рдбрд▓рд╡реЗрдпрд░ рдЬреЛрдбрд╝реЗрдВ
рдУрдкрди рдЖрдИрдбреА рдХрдиреЗрдХреНрдЯ рдПрдВрдбрдкреЙрдЗрдВрдЯ рдкреНрд░рджрд╛рди рдХрд░рдирд╛
app.UseAuthentication(); app.UseAuthorization(); app.UseIdentityServer();
рдЬреИрд╕рд╛ рдХрд┐ рдКрдкрд░ рдЙрд▓реНрд▓реЗрдЦ рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ, рд╕рд╣рд╛рдпрдХ рд╡рд┐рдзрд┐рдпреЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рд╡рд┐рдиреНрдпрд╛рд╕ рдХреЛ рдкрдврд╝рддрд╛ рд╣реИ
рдПрдкреНрд▓рд┐рдХреЗрд╢рди рд╕реЗрдЯрд┐рдВрдЧ рдореЗрдВ appsettings.json рдлрд╝рд╛рдЗрд▓ рд╣реИ, рдЬрд┐рд╕рдореЗрдВ рд╣рдореЗрдВ рдПрдХ рдирдпрд╛ рдЬреЛрдбрд╝рдирд╛ рд╣реЛрдЧрд╛
рдкрд╣рдЪрд╛рдирдХрд░реНрддрд╛ рдЕрдиреБрднрд╛рдЧред
"IdentityServer": { "Clients": { "TestIdentityAngular": { "Profile": "IdentityServerSPA" } } }
рдЗрд╕ рдЦрдВрдб рдореЗрдВ, рдПрдХ рдЧреНрд░рд╛рд╣рдХ рдХреЛ TestIdentityAngular рдирд╛рдо рд╕реЗ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ, рдЬрд┐рд╕реЗ рд╣рдо рднрд╡рд┐рд╖реНрдп рдХреЗ рдмреНрд░рд╛рдЙрдЬрд╝рд░ рдХреНрд▓рд╛рдЗрдВрдЯ рдФрд░ рдПрдХ рд╡рд┐рд╢рд┐рд╖реНрдЯ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░реЗрд╢рди рдкреНрд░реЛрдлрд╝рд╛рдЗрд▓ рдореЗрдВ рдЕрд╕рд╛рдЗрди рдХрд░реЗрдВрдЧреЗред
рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдкреНрд░реЛрдлрд╛рдЗрд▓ рдПрдХ рдирдпрд╛ рдкрд╣рдЪрд╛рдирдХрд░реНрддрд╛ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░реЗрд╢рди рдЙрдкрдХрд░рдг рд╣реИ рдЬреЛ рдХреБрдЫ рдорд╛рдкрджрдВрдбреЛрдВ рдХреЛ рдкрд░рд┐рд╖реНрдХреГрдд рдХрд░рдиреЗ рдХреА рдХреНрд╖рдорддрд╛ рдХреЗ рд╕рд╛рде рдХрдИ рдкреВрд░реНрд╡рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХреЙрдиреНрдлрд╝рд┐рдЧрд░реЗрд╢рди рдкреНрд░рджрд╛рди рдХрд░рддрд╛ рд╣реИред рд╣рдо IdentityServerSPA рдкреНрд░реЛрдлрд╝рд╛рдЗрд▓ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВрдЧреЗ, рдРрд╕реЗ рдорд╛рдорд▓реЛрдВ рдХреЗ рд▓рд┐рдП рдбрд┐рдЬрд╝рд╛рдЗрди рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ рдЬрдм рдмреНрд░рд╛рдЙрдЬрд╝рд░ рдХреНрд▓рд╛рдЗрдВрдЯ рдФрд░ рдлрд╝реНрд░реЗрдорд╡рд░реНрдХ рдПрдХ рд╣реА рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдореЗрдВ рд╕реНрдерд┐рдд рд╣реИрдВ рдФрд░ рдирд┐рдореНрди рдкреИрд░рд╛рдореАрдЯрд░ рд╣реИрдВ:
- рд░реАрдбрд╛рдпрд░реЗрдХреНрдЯ_рдпреВрд░реА рд╕рдВрд╕рд╛рдзрди рд╕реЗрдЯ / рдкреНрд░рдорд╛рдгреАрдХрд░рдг / рд▓реЙрдЧрд┐рди-рдХреЙрд▓рдмреИрдХ рдХреЗ рд▓рд┐рдП ред
- рд╕рдВрд╕рд╛рдзрди post_logout_redirect_uri, рдкрд░ / рдкреНрд░рдорд╛рдгреАрдХрд░рдг / рд▓реЙрдЧрдЖрдЙрдЯ-рдХреЙрд▓рдмреИрдХ рдкрд░ рд╕реЗрдЯ рдХрд░реЗрдВ ред
- рдХреНрд╖реЗрддреНрд░реЛрдВ рдХреЗ рд╕реЗрдЯ рдореЗрдВ рдкреНрд░рддреНрдпреЗрдХ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдПрдкреАрдЖрдИ рд╕рдВрд╕рд╛рдзрди рдХреЗ рд▓рд┐рдП рдУрдкрдирд┐рдб, рдкреНрд░реЛрдлрд╛рдЗрд▓ рд╢рд╛рдорд┐рд▓ рд╣реИрдВред
- рдЕрдиреБрдордд OIDC рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдкреНрд░рдХрд╛рд░реЛрдВ рдХрд╛ рд╕реЗрдЯ - id_token token
- рдЧреНрд░рд╛рд╣рдХ рдХреЗ рд▓рд┐рдП рдЧреНрд░рд╛рдВрдЯ рдЯрд╛рдЗрдк - рдирд┐рд╣рд┐рдд
рдЕрдиреНрдп рд╕рдВрднрд╛рд╡рд┐рдд рдкреНрд░реЛрдлрд╛рдЗрд▓ рдПрд╕рдкреАрдП (рдЖрдИрдПрд╕ 4 рдХреЗ рдмрд┐рдирд╛ рдЖрд╡реЗрджрди), рдЖрдЗрдбреЗрдВрдЯрд┐рдЯреАрд╕реЗрд╡рд░рдЬреНрд╡реЗрдЯ (рдЖрдИрдПрд╕ 4 рдХреЗ рд╕рд╛рде рд╕рд╛рдЭрд╛ рдПрдкреАрдЖрдИ), рдПрдкреАрдЖрдИ (рдЕрд▓рдЧ рдПрдкреАрдЖрдИ) рд╣реИрдВред
рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рдХреЙрдиреНрдлрд╝рд┐рдЧрд░реЗрд╢рди рд╕рдВрд╕рд╛рдзрдиреЛрдВ рдХреЛ рдкрдВрдЬреАрдХреГрдд рдХрд░рддрд╛ рд╣реИ:
- ApiResources: рдПрдХ рдПрдкреАрдЖрдИ рд╕рдВрд╕рд╛рдзрди рдЬрд┐рд╕рдХрд╛ рдирд╛рдо << appname >> рдПрдкреАрдЖрдИ рд╕рднреА рдЧреНрд░рд╛рд╣рдХреЛрдВ рдХреЗ рд▓рд┐рдП рдЧреБрдгреЛрдВ рдХреЗ рд╕рд╛рде (*) рд╣реИред
- IdentityServerResources: IdentityResources.OpenId () рдФрд░ IdentityResources.Profile ()
рдЬреИрд╕рд╛ рдХрд┐ рдЖрдк рдЬрд╛рдирддреЗ рд╣реИрдВ, IdentityServer рдЯреЛрдХрди рд╕рд╛рдЗрди рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдкреНрд░рдорд╛рдг рдкрддреНрд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реИ, рдЙрдирдХреЗ рдкреИрд░рд╛рдореАрдЯрд░ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░реЗрд╢рди рдлрд╝рд╛рдЗрд▓ рдореЗрдВ рднреА рд╕реЗрдЯ рдХрд┐рдП рдЬрд╛ рд╕рдХрддреЗ рд╣реИрдВ, рдЗрд╕рд▓рд┐рдП рдкрд░реАрдХреНрд╖рдг рдХреЗ рд╕рдордп рд╣рдо рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ
x509 рдкрд░реАрдХреНрд╖рдг рдкреНрд░рдорд╛рдг рдкрддреНрд░, рдЗрд╕рдХреЗ рд▓рд┐рдП рдЖрдкрдХреЛ рдЗрд╕реЗ appsettings.Development.json рдлрд╝рд╛рдЗрд▓ рдХреЗ "рдХреБрдВрдЬреА" рдЕрдиреБрднрд╛рдЧ рдореЗрдВ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдХрд░рдирд╛ рд╣реЛрдЧрд╛ред
"IdentityServer": { "Key": { "Type": "Development" } }
рдЕрдм рд╣рдо рдХрд╣ рд╕рдХрддреЗ рд╣реИрдВ рдХрд┐ рдмреИрдХрдПрдВрдб рдЬреЛ рдЖрдкрдХреЛ IdentityServer рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИ рддреИрдпрд╛рд░ рд╣реИ рдФрд░ рдЖрдк рдмреНрд░рд╛рдЙрдЬрд╝рд░ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдХреЛ рд▓рд╛рдЧреВ рдХрд░рдирд╛ рд╢реБрд░реВ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред
рдХреЛрдгреАрдп рдЧреНрд░рд╛рд╣рдХ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди
рд╣рдорд╛рд░реЗ рдмреНрд░рд╛рдЙрдЬрд╝рд░-рдЖрдзрд╛рд░рд┐рдд рдПрд╕рдкреАрдП рдХреЛ рдХреЛрдгреАрдп рдордВрдЪ рдкрд░ рд▓рд┐рдЦрд╛ рдЬрд╛рдПрдЧрд╛ред рдЖрд╡реЗрджрди рдореЗрдВ рджреЛ рдкреГрд╖реНрда рд╣реЛрдВрдЧреЗ, рдПрдХ рдЕрдирдзрд┐рдХреГрдд рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛рдУрдВ рдХреЗ рд▓рд┐рдП рдФрд░ рджреВрд╕рд░рд╛ рдкреНрд░рдорд╛рдгрд┐рдд рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛рдУрдВ рдХреЗ рд▓рд┐рдПред рдЙрджрд╛рд╣рд░рдг 8.1.2 рд╕рдВрд╕реНрдХрд░рдг рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВ
рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ, рднрд╡рд┐рд╖реНрдп рдХреА рд░реВрдкрд░реЗрдЦрд╛ рдмрдирд╛рдПрдВ:
ng new ClientApp
рд░реВрдЯрд┐рдВрдЧ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреЗ рдкреНрд░рд╕реНрддрд╛рд╡ рдХреЗ рд▓рд┐рдП рдЖрдкрдХреЛ "рд╣рд╛рдВ" рдХрд╛ рдЬрд╡рд╛рдм рджреЗрдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рдФрд░ рдмреВрдЯрд╕реНрдЯреНрд░реИрдк рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдкреЗрдЬ рдХреЛ рдереЛрдбрд╝рд╛ рд╕реНрдЯрд╛рдЗрд▓ рдХрд░реЗрдВ:
cd ClientApp ng add bootstrap
рдЕрдЧрд▓рд╛, рдЖрдкрдХреЛ рд╣рдорд╛рд░реЗ рдореБрдЦреНрдп рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдореЗрдВ рдПрд╕рдкреАрдП рд╣реЛрд╕реНрдЯрд┐рдВрдЧ рд╕рдорд░реНрдерди рдХреЛ рдЬреЛрдбрд╝рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ рдЖрдкрдХреЛ csproj рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдХреЛ рдареАрдХ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ - рд╣рдорд╛рд░реЗ рдмреНрд░рд╛рдЙрдЬрд╝рд░ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдЬрд╛рдирдХрд╛рд░реА рдЬреЛрдбрд╝реЗрдВред
<PropertyGroup> <TargetFramework>netcoreapp3.0</TargetFramework> <TypeScriptCompileBlocked>true</TypeScriptCompileBlocked> <TypeScriptToolsVersion>Latest</TypeScriptToolsVersion> <IsPackable>false</IsPackable> <SpaRoot>ClientApp\</SpaRoot> <DefaultItemExcludes>$(DefaultItemExcludes);$(SpaRoot)node_modules\**</DefaultItemExcludes> <BuildServerSideRenderer>false</BuildServerSideRenderer> </PropertyGroup> тАж <ItemGroup> <Content Remove="$(SpaRoot)**" /> <None Remove="$(SpaRoot)**" /> <None Include="$(SpaRoot)**" Exclude="$(SpaRoot)node_modules\**" /> </ItemGroup> <Target Name="DebugEnsureNodeEnv" BeforeTargets="Build" Condition=" '$(Configuration)' == 'Debug' And !Exists('$(SpaRoot)node_modules') "> <Exec Command="node --version" ContinueOnError="true"> <Output TaskParameter="ExitCode" PropertyName="ErrorCode" /> </Exec> <Error Condition="'$(ErrorCode)' != '0'" Text="Node.js is required to build and run this project. To continue, please install Node.js from https://nodejs.org/, and then restart your command prompt or IDE." /> <Message Importance="high" Text="Restoring dependencies using 'npm'. This may take several minutes..." /> <Exec WorkingDirectory="$(SpaRoot)" Command="npm install" /> </Target>
рдЙрд╕рдХреЗ рдмрд╛рдж, рдмреНрд░рд╛рдЙрдЬрд╝рд░ рдЕрдиреБрдкреНрд░рдпреЛрдЧреЛрдВ рдХрд╛ рд╕рдорд░реНрдерди рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╡рд┐рд╢реЗрд╖ рдирдЧреЗрдЯ рдкреИрдХреЗрдЬ рд╕реНрдерд╛рдкрд┐рдд рдХрд░реЗрдВред
dotnet add package Microsoft.AspNetCore.SpaServices.Extensions -v 3.0.0-preview7.19365.7
рдФрд░ рд╣рдо рдЗрд╕рдХреЗ рд╕рд╣рд╛рдпрдХ рддрд░реАрдХреЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВ:
рдирдП рддрд░реАрдХреЛрдВ рдХреЛ рдХреЙрд▓ рдХрд░рдиреЗ рдХреЗ рдЕрд▓рд╛рд╡рд╛, рдЖрдкрдХреЛ рд░реЗрдЬрд╝рд░ рдЗрдВрдбреЗрдХреНрд╕.рдЪрдЯрд╛рдореЗрд▓ рдФрд░ _ViewStart.chtml рдкреГрд╖реНрдареЛрдВ рдХреЛ рд╣рдЯрд╛рдирд╛ рд╣реЛрдЧрд╛ рддрд╛рдХрд┐ рдПрд╕рдкреАрдП рд╕реЗрд╡рд╛рдПрдВ рдЕрдм рд╕рд╛рдордЧреНрд░реА рдкреНрд░рджрд╛рди рдХрд░реЗрдВред
рдпрджрд┐ рд╕рдм рдХреБрдЫ рдирд┐рд░реНрджреЗрд╢реЛрдВ рдХреЗ рдЕрдиреБрд╕рд╛рд░ рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛, рдЬрдм рдЖрд╡реЗрджрди рд╢реБрд░реВ рд╣реЛрддрд╛ рд╣реИ, рддреЛ рдбрд┐рдлрд╝реЙрд▓реНрдЯ рдкреГрд╖реНрда рд╕реНрдХреНрд░реАрди рдкрд░ рджрд┐рдЦрд╛рдИ рджреЗрдЧрд╛ред

рдЕрдм рдЖрдкрдХреЛ рд░реВрдЯрд┐рдВрдЧ рдХреЛ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ, рдЗрд╕рдХреЗ рд▓рд┐рдП рд╣рдо рдкреНрд░реЛрдЬреЗрдХреНрдЯ 2 рдореЗрдВ рдЬреЛрдбрд╝рддреЗ рд╣реИрдВ
рдШрдЯрдХ:
ng generate component Home -t=true -s=true --skipTests=true ng generate component Data -t=true -s=true --skipTests=true
рд╣рдо рдЙрдиреНрд╣реЗрдВ рд░реВрдЯрд┐рдВрдЧ рдЯреЗрдмрд▓ рдореЗрдВ рд▓рд┐рдЦрддреЗ рд╣реИрдВ:
const routes: Routes = [ { path: '', component: HomeComponent, pathMatch: 'full' }, { path: 'data', component: DataComponent } ];
рдФрд░ рд╣рдо рдореЗрдиреВ рдЖрдЗрдЯрдо рдХреЛ рд╕рд╣реА рдврдВрдЧ рд╕реЗ рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП app.component.html рдлрд╝рд╛рдЗрд▓ рдХреЛ рд╕рдВрд╢реЛрдзрд┐рдд рдХрд░рддреЗ рд╣реИрдВред
<header> <nav class='navbar navbar-expand-sm navbar-toggleable-sm navbar-light bg-white border-bottom box-shadow mb-3'> <div class="container"> <a class="navbar-brand" [routerLink]='["/"]'>Client App</a> <div class="navbar-collapse collapse d-sm-inline-flex flex-sm-row-reverse" [ngClass]='{"show": isExpanded}'> <ul class="navbar-nav flex-grow"> <li class="nav-item" [routerLinkActive]='["link-active"]' [routerLinkActiveOptions]='{ exact: true }'> <a class="nav-link text-dark" [routerLink]='["/"]'>Home</a> </li> <li class="nav-item" [routerLinkActive]='["link-active"]'> <a class="nav-link text-dark" [routerLink]='["/data"]'>Web api data</a> </li> </ul> </div> </div> </nav> </header> <div style="text-align:center"> <h1> Welcome to {{ title }}! </h1> </div> <div class="router-outlet"> <router-outlet></router-outlet> </div>
рдЗрд╕ рдХрджрдо рдкрд░, рдЖрдк IdentityServer рджреНрд╡рд╛рд░рд╛ рдЬрд╛рд░реА рдЯреЛрдХрди рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдЗрдВрдЯрд░реИрдХреНрд╢рди рдХреЛ рд▓рд╛рдЧреВ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЖрд╡реЗрджрди рдврд╛рдВрдЪреЗ рдХреА рдмреБрдирд┐рдпрд╛рджреА рддреИрдпрд╛рд░реА рдХреЛ рдкреВрд░рд╛ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред
рд╣рдорд╛рд░реЗ рдПрд╕рдкреАрдП рдХреА рд░реВрдкрд░реЗрдЦрд╛ рддреИрдпрд╛рд░ рдХрд░рдиреЗ рдХреЗ рд╡рд░реНрддрдорд╛рди рдЪрд░рдг рдХреЛ рдкреВрд░рд╛ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ рдФрд░ рдЕрдм рд╣рдореЗрдВ рдУрдкреЗрдирдЖрдИрдбреА рдХрдиреЗрдХреНрдЯ рдФрд░ рдУрдЙрде рдкреНрд░реЛрдЯреЛрдХреЙрд▓ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рд╕рд░реНрд╡рд░ рднрд╛рдЧ рдХреЗ рд╕рд╛рде рдмрд╛рддрдЪреАрдд рдХреЗ рд▓рд┐рдП рдЬрд┐рдореНрдореЗрджрд╛рд░ рдореЙрдбреНрдпреВрд▓ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рдирд╛ рд╢реБрд░реВ рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдПред рд╕реМрднрд╛рдЧреНрдп рд╕реЗ, рдорд╛рдЗрдХреНрд░реЛрд╕реЙрдлреНрдЯ рдХреЗ рдбреЗрд╡рд▓рдкрд░реНрд╕ рдиреЗ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдЗрд╕ рддрд░рд╣ рдХреЗ рдХреЛрдб рдХреЛ рд▓рд╛рдЧреВ рдХрд┐рдпрд╛ рд╣реИ, рдФрд░ рдЕрдм рдЖрдк рдмрд╕ рдЗрд╕ рдореЙрдбреНрдпреВрд▓ рдХреЛ рдЙрдирд╕реЗ рдЙрдзрд╛рд░ рд▓реЗ рд╕рдХрддреЗ рд╣реИрдВред рдЪреВрдБрдХрд┐ рдореЗрд░рд╛ рд▓реЗрдЦ ASP.NET Core 3.0 рдХреЗ рдкреНрд░реА-рд░рд┐рд▓реАрдЬрд╝ 7 рдкрд░ рдЖрдзрд╛рд░рд┐рдд рд╣реИ, рдЗрд╕рд▓рд┐рдП рд╣рдо github рдкрд░ рд░рд┐рд▓реАрдЬрд╝ рдЯреИрдЧ тАЬv3.0.0-preview7.19365.7тАЭ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рд╕рднреА рдХреЛрдб рд▓реЗрдВрдЧреЗред
рдХреЛрдб рдЖрдпрд╛рдд рдХрд░рдиреЗ рд╕реЗ рдкрд╣рд▓реЗ, рдЖрдкрдХреЛ oidc-client рд▓рд╛рдЗрдмреНрд░реЗрд░реА рд╕реНрдерд╛рдкрд┐рдд рдХрд░рдирд╛ рд╣реЛрдЧрд╛, рдЬреЛ
рдмреНрд░рд╛рдЙрдЬрд╝рд░ рдЕрдиреБрдкреНрд░рдпреЛрдЧреЛрдВ рдХреЗ рд▓рд┐рдП рдХрдИ рдЗрдВрдЯрд░рдлреЗрд╕ рдкреНрд░рджрд╛рди рдХрд░рддрд╛ рд╣реИ, рд╕рд╛рде рд╣реА рд╕рд╛рде
рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рд╕рддреНрд░ рдФрд░ рдкрд╣реБрдВрдЪ рдЯреЛрдХрди рдХреЗ рдкреНрд░рдмрдВрдзрди рдХрд╛ рд╕рдорд░реНрдерди рдХрд░рддрд╛ рд╣реИред рдХреЗ рд▓рд┐рдП
рдЗрд╕рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдирд╛ рд╢реБрд░реВ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдЖрдкрдХреЛ рдЙрдЪрд┐рдд рдкреИрдХреЗрдЬ рд╕реНрдерд╛рдкрд┐рдд рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред
npm install oidc-client@1.8.0
рдЕрдм рд╣рдорд╛рд░реЗ рдПрд╕рдкреАрдП рдореЗрдВ рдПрдХ рдореЙрдбреНрдпреВрд▓ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рдирд╛ рдЖрд╡рд╢реНрдпрдХ рд╣реИ рдЬреЛ рдЖрд╡рд╢реНрдпрдХ рдкреНрд░реЛрдЯреЛрдХреЙрд▓ рдХреЗ рдЕрдиреБрд╕рд╛рд░ рдкреВрд░реНрдг рдЗрдВрдЯрд░реИрдХреНрд╢рди рдХреЛ рдПрдиреНрдХреНрд░рд┐рдкреНрдЯ рдХрд░рддрд╛ рд╣реИред рдРрд╕рд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдЖрдкрдХреЛ рдЙрдкрд░реЛрдХреНрдд ASP.NET рдХреЛрд░ рд░рд┐рдкреЙрдЬрд┐рдЯрд░реА рд▓реЗрдмрд▓ рд╕реЗ рд╕рдВрдкреВрд░реНрдг ApiAuthorizationModule рдореЙрдбреНрдпреВрд▓ рд▓реЗрдиреЗ рдХреА рдЬрд░реВрд░рдд рд╣реИ рдФрд░ рдЗрд╕рдХреА рд╕рднреА рдлрд╛рдЗрд▓реЛрдВ рдХреЛ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдореЗрдВ рдЬреЛрдбрд╝реЗрдВред
рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рдЖрдкрдХреЛ рдЗрд╕реЗ AppModule рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдХреЗ рдореБрдЦреНрдп рдореЙрдбреНрдпреВрд▓ рдореЗрдВ рдЖрдпрд╛рдд рдХрд░рдирд╛ рд╣реЛрдЧрд╛:
@NgModule({ declarations: [ AppComponent, HomeComponent, DataComponent ], imports: [ BrowserModule, HttpClientModule, ApiAuthorizationModule,//<- AppRoutingModule ], providers: [], bootstrap: [AppComponent] }) export class AppModule { }
рдЖрдпрд╛рддрд┐рдд рдореЙрдбреНрдпреВрд▓ рдореЗрдВ рдирдП рдореЗрдиреВ рдЖрдЗрдЯрдо рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдПрдХ рдРрдк-рд▓реЙрдЧрд┐рди-рдореЗрдиреВ рдШрдЯрдХ рд╣реИ,
рдпрд╣ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рдЖрдкрдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛рдУрдВ рдХреЗ рдЕрдиреБрд░реВрдк рдФрд░ рдЬреЛрдбрд╝рд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ
app.component.html рджреГрд╢реНрдп рдХреЗ рдиреЗрд╡рд┐рдЧреЗрд╢рди рдЕрдиреБрднрд╛рдЧ рдореЗрдВ рдЗрд╕рдХреЗ рд▓рд┐рдП рдПрдХ рд▓рд┐рдВрдХред
рдПрд╕рдкреАрдП рдХреНрд▓рд╛рдЗрдВрдЯ рдХреЗ рдУрдкрдирдЖрдИрдбреА рдХрдиреЗрдХреНрдЯ рдХреЛ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдкреАрдЖрдИ рдкреНрд░рд╛рдзрд┐рдХрд░рдг рдореЙрдбреНрдпреВрд▓ рдХреЛ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдореЗрдВ рдПрдХ рд╡рд┐рд╢реЗрд╖ рд╕рдорд╛рдкрди рдмрд┐рдВрджреБ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдП, рдЗрд╕рдХреЗ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХреЗ рд▓рд┐рдП
рдЗрди рдЪрд░рдгреЛрдВ рдХрд╛ рдкрд╛рд▓рди рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдП:
- рдХреНрд▓рд╛рдЗрдВрдЯ рдЖрдИрдбреА рдХреЛ рд╣рдо рдЬреЛ рд╡рд┐рдиреНрдпрд╛рд╕ рдлрд╛рдЗрд▓ appsettings.json рдореЗрдВ IdentityServer рдореЗрдВ рд╕реЗрдЯ рдХрд░рддреЗ рд╣реИрдВ, рдЙрд╕рдХреЗ рдЕрдиреБрд╕рд╛рд░ рдареАрдХ рдХрд░реЗрдВ: рдЧреНрд░рд╛рд╣рдХ рдЕрдиреБрднрд╛рдЧ, рд╣рдорд╛рд░реЗ рдорд╛рдорд▓реЗ рдореЗрдВ рдпрд╣ TestIdentityAngular рд╣реИ, рдпрд╣ api-authorization.constants.ts рдирд┐рд░рдВрддрд░ рд╕реЗрдЯ рдХреА рдкрд╣рд▓реА рдкрдВрдХреНрддрд┐ рдореЗрдВ рд▓рд┐рдЦрд╛ рдЧрдпрд╛ рд╣реИред
- рдПрдХ OidcConfigurationController рдирд┐рдпрдВрддреНрд░рдХ рдЬреЛрдбрд╝реЗрдВ рдЬреЛ рд╕реАрдзреЗ рдмреНрд░рд╛рдЙрдЬрд╝рд░ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдореЗрдВ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░реЗрд╢рди рд▓реМрдЯрд╛рдПрдЧрд╛
рдирд┐рд░реНрдорд┐рдд рдирд┐рдпрдВрддреНрд░рдХ рдХрд╛ рдХреЛрдб рдиреАрдЪреЗ рдкреНрд░рд╕реНрддреБрдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ:
[ApiController] public class OidcConfigurationController: ControllerBase { private readonly IClientRequestParametersProvider _clientRequestParametersProvider; public OidcConfigurationController(IClientRequestParametersProvider clientRequestParametersProvider) { _clientRequestParametersProvider = clientRequestParametersProvider; } [HttpGet("_configuration/{clientId}")] public IActionResult GetClientRequestParameters([FromRoute]string clientId) { var parameters = _clientRequestParametersProvider.GetClientParameters(HttpContext, clientId); return Ok(parameters); } }
рдмреИрдХрдПрдВрдб рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдХреЗ рд▓рд┐рдП рдЖрдкрдХреЛ рдмрд┐рдВрджреБ рдПрдкреАрдЖрдИ рд╕рдорд░реНрдерди рдХреЛ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░ рдХрд░рдиреЗ рдХреА рднреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред
рдЕрдм рдЖрд╡реЗрджрди рд▓реЙрдиреНрдЪ рдХрд░рдиреЗ рдХрд╛ рд╕рдордп рд╣реИред рд╢реАрд░реНрд╖ рдореЗрдиреВ рдореЗрдВ рдореБрдЦреНрдп рдкреГрд╖реНрда рдкрд░ рджреЛ рдЖрдЗрдЯрдо рджрд┐рдЦрд╛рдИ рджреЗрдиреЗ рдЪрд╛рд╣рд┐рдП - рд▓реЙрдЧрд┐рди рдФрд░ рд░рдЬрд┐рд╕реНрдЯрд░ ред рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рд╕реНрдЯрд╛рд░реНрдЯрдЕрдк рдкрд░, рдЖрдпрд╛рддрд┐рдд рдкреНрд░рд╛рдзрд┐рдХрд░рдг рдореЙрдбреНрдпреВрд▓ рдХреНрд▓рд╛рдЗрдВрдЯ рдХреА рдУрд░ рд╕реЗ рдХреНрд▓рд╛рдЗрдВрдЯ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░реЗрд╢рди рд╕реЗ рдЕрдиреБрд░реЛрдз рдХрд░реЗрдЧрд╛, рдЬрд┐рд╕реЗ рдмрд╛рдж рдореЗрдВ рдкреНрд░реЛрдЯреЛрдХреЙрд▓ рдореЗрдВ рдзреНрдпрд╛рди рдореЗрдВ рд░рдЦрд╛ рдЬрд╛рдПрдЧрд╛ред рдПрдХ рдЙрджрд╛рд╣рд░рдг рдХреЙрдиреНрдлрд╝рд┐рдЧрд░реЗрд╢рди рдЖрдЙрдЯрдкреБрдЯ рдиреАрдЪреЗ рджрд┐рдЦрд╛рдпрд╛ рдЧрдпрд╛ рд╣реИ:
{ "authority": "https://localhost:44367", "client_id": "TestIdentityAngular", "redirect_uri": "https://localhost:44367/authentication/login-callback", "post_logout_redirect_uri": "https://localhost:44367/authentication/logout-callback", "response_type": "id_token token", "scope": "IdentityServer4WebAppAPI openid profile" }
рдЬреИрд╕рд╛ рдХрд┐ рдЖрдк рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВ, рдЗрдВрдЯрд░реИрдХреНрд╢рди рдХреЗ рджреМрд░рд╛рди рдХреНрд▓рд╛рдЗрдВрдЯ рдЖрдИрдбреА рдЯреЛрдХрди рдФрд░ рдПрдХреНрд╕реЗрд╕ рдЯреЛрдХрди рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреА рдЙрдореНрдореАрдж рдХрд░рддрд╛ рд╣реИ, рдФрд░ рдпрд╣ рд╣рдорд╛рд░реЗ рдПрдкреАрдЖрдИ рддрдХ рдкрд╣реБрдВрдЪ рдХреНрд╖реЗрддреНрд░ рдХреЗ рд▓рд┐рдП рднреА рдХреЙрдиреНрдлрд╝рд┐рдЧрд░ рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИред
рдЕрдм, рдпрджрд┐ рд╣рдо рд▓реЙрдЧрд┐рди рдореЗрдиреВ рдЖрдЗрдЯрдо рдХрд╛ рдЪрдпрди рдХрд░рддреЗ рд╣реИрдВ, рддреЛ рд╣рдореЗрдВ рд╣рдорд╛рд░реЗ IdentityServer4 рдХреЗ рдкреГрд╖реНрда рдкрд░ рдкреБрдирд░реНрдирд┐рд░реНрджреЗрд╢рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдП рдФрд░ рдпрд╣рд╛рдВ рд╣рдо рд▓реЙрдЧрд┐рди рдФрд░ рдкрд╛рд╕рд╡рд░реНрдб рджрд░реНрдЬ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рдФрд░ рдпрджрд┐ рд╡реЗ рд╕рд╣реА рд╣реИрдВ, рддреЛ рд╣рдореЗрдВ рддреБрд░рдВрдд рдмреНрд░рд╛рдЙрдЬрд╝рд░ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдкрд░ рд╡рд╛рдкрд╕ рд╕реНрдерд╛рдирд╛рдВрддрд░рд┐рдд рдХрд░ рджрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛, рдЬреЛ рдмрджрд▓реЗ рдореЗрдВ id_token рдФрд░ access_token рдкреНрд░рд╛рдкреНрдд рдХрд░реЗрдЧрд╛ред рдЬреИрд╕рд╛ рдХрд┐ рдЖрдк рдиреАрдЪреЗ рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВ, рдРрдк-рд▓реЙрдЧрд┐рди-рдореЗрдиреВ рдШрдЯрдХ рдиреЗ рд╕реНрд╡рдпрдВ рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХрд┐рдпрд╛ рдерд╛ рдХрд┐ рдкреНрд░рд╛рдзрд┐рдХрд░рдг рдиреЗ рд╕рдлрд▓рддрд╛рдкреВрд░реНрд╡рдХ рдкреВрд░рд╛ рдХрд┐рдпрд╛ рдФрд░ "рдЧреНрд░реАрдЯрд┐рдВрдЧ" рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд┐рдпрд╛, рд╕рд╛рде рд╣реА рд▓реЙрдЧрдЖрдЙрдЯ рдХреЗ рд▓рд┐рдП рдПрдХ рдмрдЯрди рднреАред

рдЬрдм рдЖрдк рдмреНрд░рд╛рдЙрдЬрд╝рд░ рдореЗрдВ "рдбреЗрд╡рд▓рдкрд░ рдЯреВрд▓" рдЦреЛрд▓рддреЗ рд╣реИрдВ, рддреЛ рдЖрдк рдУрдЖрдИрдбреАрд╕реА / рдУрдерде рдкреНрд░реЛрдЯреЛрдХреЙрд▓ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдмреИрдХрд╕реНрдЯреЗрдЬ рд╕рднреА рдЗрдВрдЯрд░реИрдХреНрд╢рди рдореЗрдВ рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВред рдпрд╣ рдкреНрд░рд╛рдзрд┐рдХрд░рдг рд╕рд░реНрд╡рд░ рдЬрд╛рдирдХрд╛рд░реА рдкреНрд░рд╛рдкреНрдд рдХрд░ рд░рд╣рд╛ рд╣реИ
рдПрдВрдбрдкреЙрдЗрдВрдЯ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ .well- рдЬрд╛рдирд╛ рдЬрд╛рддрд╛ рд╣реИ / рдУрдкреЗрди-рдХреЙрдиреНрдлрд╝рд┐рдЧрд░реЗрд╢рди рдФрд░ рдкреВрд▓рд┐рдВрдЧ рд╕реЗрд╢рди рдПрдХреНрдЯрд┐рд╡рд┐рдЯреА рдХрдиреЗрдХреНрдЯ / рдЪреЗрдХрд╕реЗрд╢рди рдПрдХреНрд╕реЗрд╕ рдкреЙрдЗрдВрдЯ рдХреЗ рдЬрд░рд┐рдПред рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рдкреНрд░рд╛рдзрд┐рдХрд░рдг рдореЙрдбреНрдпреВрд▓ "рдЯреЛрдХрди рдХреЗ рдореВрдХ рдЕрджреНрдпрддрди" рддрдВрддреНрд░ рдХреЗ рд▓рд┐рдП рдХреЙрдиреНрдлрд╝рд┐рдЧрд░ рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ, рдЬрдм рдкрд╣реБрдВрдЪ рдЯреЛрдХрди рд╕рдорд╛рдкреНрдд рд╣реЛ рдЬрд╛рддрд╛ рд╣реИ, рддреЛ рд╕рд┐рд╕реНрдЯрдо рд╕реНрд╡рддрдВрддреНрд░ рд░реВрдк рд╕реЗ рдПрдХ рдЫрд┐рдкреЗ рд╣реБрдП iframe рдореЗрдВ рдкреНрд░рд╛рдзрд┐рдХрд░рдг рдЪрд░рдгреЛрдВ рдХреЛ рдкрд╛рд░рд┐рдд рдХрд░рддрд╛ рд╣реИред рдЖрдк AuthorI.service.ts рдлрд╝рд╛рдЗрд▓ рдореЗрдВ "рдЭреВрдареЗ" рдореЗрдВ рд╢рд╛рдорд┐рд▓ рдХрд░реЗрдВ IndITTokenInSilentRenew рдкреИрд░рд╛рдореАрдЯрд░ рдХрд╛ рдорд╛рди рд╕реЗрдЯ рдХрд░рдХреЗ рдЯреЛрдХрди-рдЕрдкрдбреЗрдЯ рдХреЛ рдЕрдХреНрд╖рдо рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред
рдЕрдм рдЖрдк рдПрд╕рдкреАрдП рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдХреЗ рдШрдЯрдХреЛрдВ рд╕реЗ рдЕрдирдзрд┐рдХреГрдд рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛рдУрдВ рддрдХ рдкрд╣реБрдВрдЪ рдХреЛ рдкреНрд░рддрд┐рдмрдВрдзрд┐рдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рд╕рд╛рде рд╣реА рдкреАрда рдкрд░ рдХреБрдЫ рдПрдкреАрдЖрдИ рдирд┐рдпрдВрддреНрд░рдХ рднреАред рдХреБрдЫ рдПрдкреАрдЖрдИ рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдо рдореЙрдбрд▓ рдлрд╝реЛрд▓реНрдбрд░ рдореЗрдВ рдПрдХ ExchangeRateItem рд╡рд░реНрдЧ , рд╕рд╛рде рд╣реА рдирд┐рдпрдВрддреНрд░рдХ рдлрд╝реЛрд▓реНрдбрд░ рдореЗрдВ рдХреБрдЫ рдпрд╛рджреГрдЪреНрдЫрд┐рдХ рдбреЗрдЯрд╛ рд▓реМрдЯрд╛рддреЗ рд╣реИрдВ, рдЬреЛ рдПрдХ рдирд┐рдпрдВрддреНрд░рдХ рдмрдирд╛рдПрдВрдЧреЗред
рдЕрдЧрд▓рд╛, рдлреНрд░рдВрдЯ-рдПрдВрдб рд╕рд╛рдЗрдб рдкрд░, рдПрдХ рдирдпрд╛ рдШрдЯрдХ рдмрдирд╛рдПрдВ рдЬреЛ рдкреНрд░рд╛рдкреНрдд рд╣реЛрдЧрд╛
рдФрд░ рдмрд╕ рдмрдирд╛рдП рдЧрдП рдирд┐рдпрдВрддреНрд░рдХ рд╕реЗ рд╡рд┐рдирд┐рдордп рджрд░реЛрдВ рдкрд░ рдбреЗрдЯрд╛ рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд░реЗрдВред
ng generate component ExchangeRate -t=true -s=true --skipTests=true
рдШрдЯрдХ рдХреА рд╕рд╛рдордЧреНрд░реА рдЗрд╕ рддрд░рд╣ рджрд┐рдЦрдиреА рдЪрд╛рд╣рд┐рдП:
рдХреЛрдб import { Component, OnInit, Input } from '@angular/core'; import { HttpClient } from '@angular/common/http'; import { Observable, of, Subject } from 'rxjs'; import { catchError } from 'rxjs/operators'; @Component({ selector: 'app-exchange-rate', template: ` <div class="alert alert-danger" *ngIf="errorMessage | async as msg"> {{msg}} </div> <table class='table table-striped'> <thead> <tr> <th>From currency</th> <th>To currency</th> <th>Rate</th> </tr> </thead> <tbody> <tr *ngFor="let rate of rates | async"> <td>{{ rate.fromCurrency }} </td> <td>{{ rate.toCurrency }}</td> <td>{{ rate.value }}</td> </tr> </tbody> </table> `, styles: [] }) export class ExchangeRateComponent implements OnInit { public rates: Observable<ExchangeRateItem[]>; public errorMessage: Subject<string>; @Input() public apiUrl: string; constructor(private http: HttpClient) { this.errorMessage = new Subject<string>(); } ngOnInit() { this.rates = this.http.get<ExchangeRateItem[]>("/api/"+this.apiUrl).pipe(catchError(this.handleError(this.errorMessage)) ); } private handleError(subject: Subject<string>): (te:any) => Observable<ExchangeRateItem[]> { return (error) => { let message = ''; if (error.error instanceof ErrorEvent) { message = `Error: ${error.error.message}`; } else { message = `Error Code: ${error.status}\nMessage: ${error.message}`; } subject.next(message); let emptyResult: ExchangeRateItem[] = []; return of(emptyResult); } } } interface ExchangeRateItem { fromCurrency: string; toCurrency: string; value: number; }
рдЕрдм рдпрд╣ рдРрдк-рдбреЗрдЯрд╛ рдкреГрд╖реНрда рдкрд░ рдЗрд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рд╢реБрд░реВ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдмрдирд╛ рд╣реБрдЖ рд╣реИ, рдмрд╕ рдЯреЗрдореНрдкрд▓реЗрдЯ рдореЗрдВ <app-exchange-rate-apiUrl = "рджрд░реЗрдВ"> </ app-exchange-rate> рд▓рд┐рдЦрдХрд░ рдФрд░ рдЖрдк рдлрд┐рд░ рд╕реЗ рдкрд░рд┐рдпреЛрдЬрдирд╛ рд╢реБрд░реВ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рдЬрдм рд╣рдо рд▓рдХреНрд╖реНрдп рдкрде рдкрд░ рдиреЗрд╡рд┐рдЧреЗрдЯ рдХрд░рддреЗ рд╣реИрдВ, рддреЛ рд╣рдо рджреЗрдЦреЗрдВрдЧреЗ рдХрд┐ рдШрдЯрдХ рдиреЗ рдбреЗрдЯрд╛ рдкреНрд░рд╛рдкреНрдд рдХрд┐рдпрд╛ рдФрд░ рдЗрд╕реЗ рдПрдХ рддрд╛рд▓рд┐рдХрд╛ рдореЗрдВ рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд┐рдпрд╛ред
рдЕрдЧрд▓рд╛, рд╣рдо рдирд┐рдпрдВрддреНрд░рдХ рдХреЗ рдПрдкреАрдЖрдИ рддрдХ рдкрд╣реБрдВрдЪ рдХреЗ рдкреНрд░рд╛рдзрд┐рдХрд░рдг рдХреЗ рд▓рд┐рдП рдПрдХ рдЕрдиреБрд░реЛрдз рдЬреЛрдбрд╝рдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд░реЗрдВрдЧреЗред рдРрд╕рд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, ExchangeRateController рд╡рд░реНрдЧ рдкрд░ [рдкреНрд░рд╛рдзрд┐рдХрд░рдг] рд╡рд┐рд╢реЗрд╖рддрд╛ рдЬреЛрдбрд╝реЗрдВ рдФрд░ рдлрд┐рд░ рд╕реЗ рдПрд╕рдкреАрдП рдЪрд▓рд╛рдПрдВ, рд╣рд╛рд▓рд╛рдВрдХрд┐, рдЬрдм рд╣рдо рдЕрдкрдиреЗ рдПрдкреАрдЖрдИ рдХреЛ рдХреЙрд▓ рдХрд░рдиреЗ рд╡рд╛рд▓реЗ рдШрдЯрдХ рдкрд░ рд╡рд╛рдкрд╕ рдЬрд╛рддреЗ рд╣реИрдВ, рддреЛ рд╣рдо рдПрдХ рддреНрд░реБрдЯрд┐ рджреЗрдЦреЗрдВрдЧреЗ, рдЬреЛ рдЗрдВрдЧрд┐рдд рдХрд░рддрд╛ рд╣реИред рдкреНрд░рд╛рдзрд┐рдХрд░рдг рд╣реЗрдбрд░ред

рдЖрдЙрдЯрдЧреЛрдЗрдВрдЧ рдЕрдиреБрд░реЛрдзреЛрдВ рдХреЛ рдПрдХ рдкреНрд░рд╛рдзрд┐рдХрд░рдг рдЯреЛрдХрди рдХреЛ рд╕рд╣реА рдврдВрдЧ рд╕реЗ рдЬреЛрдбрд╝рдиреЗ рдХреЗ рд▓рд┐рдП, рдЖрдк рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ
рдХреЛрдгреАрдп рдЗрдВрдЯрд░рд╕реЗрдкреНрдЯрд░ рдЗрдВрдЯрд░рд╕реЗрдкреНрдЯрд░ рддрдВрддреНрд░ рдХреЛ рд╕рдВрд▓рдЧреНрди рдХрд░реЗрдВред рд╕реМрднрд╛рдЧреНрдп рд╕реЗ, рдЖрдпрд╛рддрд┐рдд рдореЙрдбреНрдпреВрд▓ рдореЗрдВ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдЖрд╡рд╢реНрдпрдХ рдкреНрд░рдХрд╛рд░ рд╢рд╛рдорд┐рд▓ рд╣реИрдВ, рд╣рдореЗрдВ рдХреЗрд╡рд▓ рдЖрд╡реЗрджрди рдХреЗ рдЖрдзрд╛рд░ рдореЙрдбреНрдпреВрд▓ рдореЗрдВ рдЗрд╕реЗ рдкрдВрдЬреАрдХреГрдд рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред
providers: [ { provide: HTTP_INTERCEPTORS, useClass: AuthorizeInterceptor, multi: true } ],
рдЗрди рдЪрд░рдгреЛрдВ рдХреЗ рдмрд╛рдж, рд╕рдм рдХреБрдЫ рд╕рд╣реА рдврдВрдЧ рд╕реЗ рдХрд╛рдо рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдПред рдпрджрд┐ рдЖрдк рдбреЗрд╡рд▓рдкрд░ рдЯреВрд▓ рдХреЛ рдлрд┐рд░ рд╕реЗ рджреЗрдЦрддреЗ рд╣реИрдВ, рддреЛ рдмреНрд░рд╛рдЙрдЬрд╝рд░ рдХреЛ рдирдпрд╛ рдмрд┐рдпрд░рд░ access_token рдкреНрд░рд╛рдзрд┐рдХрд░рдг рд╣реЗрдбрд░ рджрд┐рдЦрд╛рдИ рджреЗрдЧрд╛ред рдмреИрдХрдПрдВрдб рдкрд░, рдЗрд╕ рдЯреЛрдХрди рдХреЛ IdentityServer рджреНрд╡рд╛рд░рд╛ рдорд╛рдиреНрдп рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ рдФрд░ рдпрд╣ рд╕реБрд░рдХреНрд╖рд┐рдд рдПрдкреАрдЖрдИ рдмрд┐рдВрджреБ рдХреЛ рдХреЙрд▓ рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рднреА рджреЗрдЧрд╛ред
рдкреНрд░рд╛рдзрд┐рдХрд░рдг рд╕рд░реНрд╡рд░ рдХреЗ рд╕рд╛рде рдПрдХреАрдХрд░рдг рдХреЗ рдЙрджрд╛рд╣рд░рдг рдХреЗ рдЕрдВрдд рдореЗрдВ, рдЖрдк рдПрд╕рдкреАрдП рдореЗрдВ рд╡рд┐рдирд┐рдордп рджрд░ рдбреЗрдЯрд╛ рдХреЗ рд╕рд╛рде рдорд╛рд░реНрдЧ рдкрд░ рд╕рдХреНрд░рд┐рдпрдг рдЧрд╛рд░реНрдб рд░рдЦ рд╕рдХрддреЗ рд╣реИрдВ, рдпрд╣ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛рдУрдВ рдХреЛ рдкреГрд╖реНрда рдкрд░ рд╕реНрд╡рд┐рдЪ рдХрд░рдиреЗ рд╕реЗ рд░реЛрдХ рджреЗрдЧрд╛ рдпрджрд┐ рд╡реЗ рд╡рд░реНрддрдорд╛рди рдореЗрдВ рдЕрдзрд┐рдХреГрдд рдирд╣реАрдВ рд╣реИрдВред рдпрд╣ рд░рдХреНрд╖рдХ рдкрд╣рд▓реЗ рд╕реЗ рдЖрдпрд╛рддрд┐рдд рдореЙрдбреНрдпреВрд▓ рдореЗрдВ рднреА рдкреНрд░рд╕реНрддреБрдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ, рдЖрдкрдХреЛ рдЗрд╕реЗ рд▓рдХреНрд╖реНрдп рдорд╛рд░реНрдЧ рдкрд░ рд▓рдЯрдХрд╛рдП рдЬрд╛рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред
{ path: 'data', component: DataComponent, canActivate: [AuthorizeGuard] }
рдЕрдм, рдЙрд╕ рд╕реНрдерд┐рддрд┐ рдореЗрдВ рдЬрдм рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдиреЗ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдореЗрдВ рд▓реЙрдЧ рдЗрди рдирд╣реАрдВ рдХрд┐рдпрд╛ рд╣реИ рдФрд░ рд╣рдорд╛рд░реЗ рд╕рдВрд░рдХреНрд╖рд┐рдд рдШрдЯрдХ рдХреЗ рд▓рд┐рдП рдПрдХ рд▓рд┐рдВрдХ рдХрд╛ рдЪрдпрди рдХрд┐рдпрд╛ рд╣реИ, рддреЛ рдЙрд╕реЗ рддреБрд░рдВрдд рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдирд╛рдо рдФрд░ рдкрд╛рд╕рд╡рд░реНрдб рджрд░реНрдЬ рдХрд░рдиреЗ рдХреЗ рдЕрдиреБрд░реЛрдз рдХреЗ рд╕рд╛рде рдкреНрд░рд╛рдзрд┐рдХрд░рдг рдкреГрд╖реНрда рдкрд░ рдкреБрдирдГ рдирд┐рд░реНрджреЗрд╢рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ред рдкрд░рд┐рдгрд╛рдореА рдХреЛрдб рдЬреАрдердм рдкрд░ рдЙрдкрд▓рдмреНрдз рд╣реИред
Google рдкреНрд░рджрд╛рддрд╛ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдмрд╛рд╣рд░реА рд▓реЙрдЧрд┐рди рдХрдиреЗрдХреНрдЯ рдХрд░рдирд╛
ASP.NET Core 1.1 / 2.0 + рдХреЗ рд▓рд┐рдП Google рдЦрд╛рддреЛрдВ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рд▓реЙрдЧрд┐рди рдХреЛ рдЬреЛрдбрд╝рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдЕрд▓рдЧ Microsoft.AspNetCore.Authentication.Google рдиреБрдЧреЗрдЯ рдкреИрдХреЗрдЬ рд╣реИ, рд╣рд╛рд▓рд╛рдБрдХрд┐, рдирд┐рдЧрдо рдХреА рдиреАрддрд┐ рдореЗрдВ рдкрд░рд┐рд╡рд░реНрддрди рдХреЗ рдХрд╛рд░рдг, Microsoft рдХреЗ рдкрд╛рд╕ ASP.NET Core ++ рдХреЗ рд▓рд┐рдП рдпреЛрдЬрдирд╛ рд╣реИ рдЗрд╕реЗ рдЕрдкреНрд░рдЪрд▓рд┐рдд рдХреЗ рд░реВрдк рдореЗрдВ рдкрд╣рдЪрд╛рдиреЗрдВред рдФрд░ рдЕрдм рдпрд╣ рд╕рд╣рд╛рдпрдХ рд╡рд┐рдзрд┐ OpenIdConnectExtensions рдФрд░ AddOpenIdConnect рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдХрдиреЗрдХреНрдЯ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЕрдиреБрд╢рдВрд╕рд┐рдд рд╣реИ, рдЬрд┐рд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рд╣рдо рдЗрд╕ рд▓реЗрдЦ рдореЗрдВ рдХрд░реЗрдВрдЧреЗред
OpenIdConnect рдПрдХреНрд╕рдЯреЗрдВрд╢рди рд╕реНрдерд╛рдкрд┐рдд рдХрд░реЗрдВ:
dotnet add package Microsoft.AspNetCore.Authentication.OpenIdConnect -v 3.0.0-preview7.19365.7
рдЖрд░рдВрдн рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдореЗрдВ Google - Id Client рдФрд░ Client Secret рд╕реЗ рджреЛ рдкреНрд░рдореБрдЦ рдорд╛рди рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рд╣реЛрдВрдЧреЗ, рдЗрд╕рдХреЗ рд▓рд┐рдП рдЗрди рдЪрд░рдгреЛрдВ рдХрд╛ рдкрд╛рд▓рди рдХрд░рдирд╛ рдкреНрд░рд╕реНрддрд╛рд╡рд┐рдд рд╣реИ:
- рд▓рд┐рдВрдХ рдХрд╛ рдкрд╛рд▓рди рдХрд░реЗрдВ рдФрд░ "рд╕рдВрдкрд░реНрдХ рдПрдХ рдкрд░рд┐рдпреЛрдЬрдирд╛" рдмрдЯрди рдХрд╛ рдЪрдпрди рдХрд░реЗрдВред
- рджрд┐рдЦрд╛рдИ рджреЗрдиреЗ рд╡рд╛рд▓реЗ рд╕рдВрд╡рд╛рдж рдореЗрдВ, рд╡реЗрдм рд╕рд░реНрд╡рд░ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдХрд░реЗрдВред
- ┬лAuthorized redirect URI┬╗ Google (.. https://localhost:44301/ , https://localhost:44301/signin-google )
- ClientID Client Secret.
- , , URL .
Secret Manager . , .
dotnet user-secrets init dotnet user-secrets set "Authentication:Google:ClientId" " ClientID" dotnet user-secrets set "Authentication:Google:ClientSecret" " ClientSecret"
Google.
services.AddAuthentication() .AddOpenIdConnect("Google", "Google", o => { IConfigurationSection googleAuthNSection = Configuration.GetSection("Authentication:Google"); o.ClientId = googleAuthNSection["ClientId"]; o.ClientSecret = googleAuthNSection["ClientSecret"]; o.Authority = "https://accounts.google.com"; o.ResponseType = OpenIdConnectResponseType.Code; o.CallbackPath = "/signin-google"; }) .AddIdentityServerJwt();
,
Google. , , SPA .

, , OAuth , . Nuget .
Windows
, SPA Microsoft, ActiveDirectory. , Html ASP.NET, WebForms .., Windows WindowsIdentity, , . Identity Server, Windows, claims id_token access_token . , IS4 , ,
github . , ASP.NET Core Identity 3.0.
Identity, Razor Login ExternalLogin ( CLI aspnet-codegenerator ):
dotnet add package Microsoft.EntityFrameworkCore.SqlServer dotnet add package Microsoft.VisualStudio.Web.CodeGeneration.Design dotnet aspnet-codegenerator identity -dc IdentityServer4WebApp.Data.ApplicationDbContext --files "Account.Login;Account.ExternalLogin"
, Area Identity , .
, . , Identity I AuthenticationSchemeProvider. GetAllSchemesAsync() DisplayName != null, Windows DisplayName = null. LoginModel OnGetAsync :
ExternalLogins = (await _signInManager.GetExternalAuthenticationSchemesAsync()).ToList();
private readonly AuthenticationSchemeProvider _schemeProvider . View Login.cshtml :
<button type="submit" class="btn btn-primary" name="provider" value="@provider.Name" title="Log in using your @provider.DisplayName account">@provider.DisplayName</button> << >> <button type="submit" class="btn btn-primary" name="provider" value="@provider.Name" title="Log in using your @(provider.DisplayName ??provider.Name) account">@(provider.DisplayName ??provider.Name)</button>
, windows launchSettings.json
( IIS, web.config ).
"iisSettings": { "windowsAuthentication": true, "anonymousAuthentication": true, "iisExpress": { "applicationUrl": "http://localhost:15479", "sslPort": 44301 } },
┬лWindows┬╗ .

SPA IdentityServer . ┬л┬╗ [AllowAnonymous] LoginModel [Authorize(AuthenticationSchemes = "Windows")] , , WindowsIdentity.
ExternalLogin , Identity Windows . ProcessWindowsLoginAsync .
private async Task<IActionResult> ProcessWindowsLoginAsync(string returnUrl) { var result = await HttpContext.AuthenticateAsync(IISDefaults.AuthenticationScheme); if (result?.Principal is WindowsPrincipal wp) { var redirectUrl = Url.Page("./ExternalLogin", pageHandler: "Callback", values: new { returnUrl }); var props = _signInManager.ConfigureExternalAuthenticationProperties(IISDefaults.AuthenticationScheme, redirectUrl); props.Items["scheme"] = IISDefaults.AuthenticationScheme; var id = new ClaimsIdentity(IISDefaults.AuthenticationScheme); id.AddClaim(new Claim(JwtClaimTypes.Subject, wp.Identity.Name)); id.AddClaim(new Claim(JwtClaimTypes.Name, wp.Identity.Name)); id.AddClaim(new Claim(ClaimTypes.NameIdentifier, wp.Identity.Name)); var wi = wp.Identity as WindowsIdentity; var groups = wi.Groups.Translate(typeof(NTAccount)); var hasUsersGroup = groups.Any(i => i.Value.Contains(@"BUILTIN\Users", StringComparison.OrdinalIgnoreCase)); id.AddClaim(new Claim("hasUsersGroup", hasUsersGroup.ToString())); await HttpContext.SignInAsync(IdentityConstants.ExternalScheme, new ClaimsPrincipal(id), props); return Redirect(props.RedirectUri); } return Challenge(IISDefaults.AuthenticationScheme); }
, .
ExternalLoginModel.OnPost :
if (IISDefaults.AuthenticationScheme == provider) { return await ProcessWindowsLoginAsync(returnUrl); }
Claim Windows Claim ┬лhasUsersGroup┬╗, ID access, . ASP.NET Identity UserClaims. ExternalLoginModel .
private async Task UpdateClaims(ExternalLoginInfo info, ApplicationUser user, params string[] claimTypes) { if (claimTypes == null) { return; } var claimTypesHash = new HashSet<string>(claimTypes); var claims = (await _userManager.GetClaimsAsync(user)).Where(c => claimTypesHash.Contains(c.Type)).ToList(); await _userManager.RemoveClaimsAsync(user, claims); foreach (var claimType in claimTypes) { if (info.Principal.HasClaim(c => c.Type == claimType)) { claims = info.Principal.FindAll(claimType).ToList(); await _userManager.AddClaimsAsync(user, claims); } } }
OnPostConfirmationAsync (
).
result = await _userManager.AddLoginAsync(user, info); if (result.Succeeded) { await _signInManager.SignInAsync(user, isPersistent: false); _logger.LogInformation("User created an account using {Name} provider.", info.LoginProvider); await UpdateClaims(info, user, "hasUsersGroup");
OnGetCallbackAsync , .
var result = await _signInManager.ExternalLoginSignInAsync(info.LoginProvider, info.ProviderKey, isPersistent: false, bypassTwoFactor : true); if (result.Succeeded) { var user = await _userManager.FindByLoginAsync(info.LoginProvider, info.ProviderKey); await UpdateClaims(info, user, "hasUsersGroup");
, WebAPI
┬лhasUsersGroup┬╗. ┬лShouldHasUsersGroup┬╗
services.AddAuthorization(options => { options.AddPolicy("ShouldHasUsersGroup", policy => { policy.RequireClaim("hasUsersGroup");}); });
ExchangeRateController
Policy.
[Authorize(Policy = "ShouldHasUsersGroup")] [HttpGet("api/internalrates")] public IEnumerable<ExchangeRateItem> GetInternalRates() { return Get().Select(i=>{i.Value=Math.Round(i.Value-0.02,2);return i;}); }
view .
ng generate component InternalData -t=true -s=true --skipTests=true
template .
//internal-data.component.ts: template: `<app-exchange-rate apiUrl="internalrates"></app-exchange-rate> `, //app-routing.module.ts: { path: ' internaldata', component: InternalDataComponent, canActivate: [AuthorizeGuard] } //app.component.html: <li class="nav-item" [routerLinkActive]='["link-active"]'> <a class="nav-link text-dark" [routerLink]='["/internaldata"]'>Internal api data</a> </li>
, , . , accsee_token
claim hasUsersGroup ,
ApiResources . , , appsettings.json , Startup. ConfigureServices .
services.AddIdentityServer() .AddApiAuthorization<ApplicationUser, ApplicationDbContext>(options => { var apiResource = options.ApiResources.First(); apiResource.UserClaims = new[] { "hasUsersGroup" }; });
, , windows , .
, тАУ Guard claim ┬лhasUsersGroup┬╗ ┬л ┬╗. Guard :
ng generate guard AuthorizeWindowsGroupGuard --skipTests=true
:
import { Injectable } from '@angular/core'; import { Observable } from 'rxjs'; import { map,tap} from 'rxjs/operators'; import { CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot, Router, UrlTree } from '@angular/router'; import { AuthorizeService } from "./authorize.service"; import { ApplicationPaths, QueryParameterNames } from './api-authorization.constants'; @Injectable({ providedIn: 'root' }) export class AuthorizeWindowsGroupGuardGuard implements CanActivate{ constructor(private authorize: AuthorizeService, private router: Router) {} canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree { return this.authorize.getUser().pipe(map((u: any) => !!u && !!u.hasUsersGroup)).pipe(tap((isAuthorized:boolean) => this.handleAuthorization(isAuthorized, state)));; } private handleAuthorization(isAuthenticated: boolean, state: RouterStateSnapshot) { if (!isAuthenticated) { window.location.href = "/Identity/Account/Login?" + QueryParameterNames.ReturnUrl + "=/"; } } }
, , .
{ path: 'internaldata', component: InternalDataComponent, canActivate: [AuthorizeWindowsGroupGuardGuard]
IdentityServer, claims ( sub , profile ), ┬лhasUsersGroup┬╗. IdentityResource, - IdentityResources Startup.ConfigureServices .
var identityResource = new IdentityResource { Name = "customprofile", DisplayName = "Custom profile", UserClaims = new[] { "hasUsersGroup" }, }; identityResource.Properties.Add(ApplicationProfilesPropertyNames.Clients, "*"); options.IdentityResources.Add(identityResource);
- , windows ┬л ┬╗ SPA тАУ , , Guard .
рдирд┐рд╖реНрдХрд░реНрд╖
, ASP.NET Core 3.0 IdentityServer4, . preview , . , github .