ASP. NET 웹 Api 보안

16668 단어 asp.net
전송 주소:http://www.cnblogs.com/fzrain/p/3552423.html
웹 Api 에서 Https 강제 사용
우 리 는 IIS 단계 에서 웹 Api 전 체 를 설정 하여 Https 를 강제 적 으로 사용 할 수 있 지만, 어떤 경우 에는 하나의 action 에 대해 Https 를 강제 적 으로 사용 해 야 할 수도 있 고, 다른 방법 은 http 를 사용 할 수도 있 습 니 다.
이 를 위해 웹 Api 의 filers - filter (필터) 를 사용 하 는 주요 역할 은 우리 가 방법 을 실행 하기 전에 코드 를 실행 할 수 있 는 것 입 니 다.접촉 한 적 이 없 으 면 다음 그림 을 통 해 간단하게 이해 하고 대신 이 건 너 뛸 수 있 습 니 다.
ASP.NET Web Api 安全性_第1张图片
우리 가 새로 만 든 filter 는 안전 한 지 여 부 를 검사 하 는 데 사 용 될 것 입 니 다. 안전 하지 않 으 면 filter 는 요청 을 중지 하고 해당 되 는 것 을 되 돌려 줍 니 다. 요청 은 https 여야 합 니 다.
구체 적 인 방법: Authorization FilterAttribute 에서 filter 를 만 들 고 OnAuthorization 을 다시 써 서 우리 의 수 요 를 실현 합 니 다.
웹 사이트 루트 디 렉 터 리 에 "Filters" 폴 더 를 만 듭 니 다. "ForceHttpsAttribute" 는 "System. Web. Http. Filters. Authorization FilterAttribute" 에서 계승 합 니 다. 아래 코드 는 다음 과 같 습 니 다.
public class ForceHttpsAttribute : AuthorizationFilterAttribute
    {
        public override void OnAuthorization(System.Web.Http.Controllers.HttpActionContext actionContext)
        {
            var request = actionContext.Request;
 
            if (request.RequestUri.Scheme != Uri.UriSchemeHttps)
            {
                var html = "<p>Https is required</p>";
 
                if (request.Method.Method == "GET")
                {
                    actionContext.Response = request.CreateResponse(HttpStatusCode.Found);
                    actionContext.Response.Content = new StringContent(html, Encoding.UTF8, "text/html");
 
                    UriBuilder httpsNewUri = new UriBuilder(request.RequestUri);
                    httpsNewUri.Scheme = Uri.UriSchemeHttps;
                    httpsNewUri.Port = 443;//HTTPS(securely transferring web pages)   ,       443/tcp 443/udp;
 
                    actionContext.Response.Headers.Location = httpsNewUri.Uri;
                }
                else
                {
                    actionContext.Response = request.CreateResponse(HttpStatusCode.NotFound);
                    actionContext.Response.Content = new StringContent(html, Encoding.UTF8, "text/html");
                }
 
            }
        }
    }


위의 코드 에서 저 희 는 actionContext 매개 변 수 를 통 해 request 와 response 대상 을 받 았 습 니 다. 저 희 는 클 라 이언 트 의 요청 을 판단 합 니 다. https 가 아니라면 클 라 이언 트 에 직접 응답 하려 면 https 를 사용 해 야 합 니 다.
여기 서 요청 이 Get 인지 다른 (Post, Delete, Put) 인지 구분 해 야 합 니 다. Http 를 사용 한 Get 요청 으로 자원 에 접근 하 는 경우 https 를 사용 하여 연결 을 만 들 고 Header 에 응답 하 는 Location 에 추가 할 것 입 니 다.이렇게 하면 클 라 이언 트 가 자동 으로 https 를 사용 하여 Get 요청 을 보 냅 니 다.
Get 요청 이 아 닌 경우 404 를 직접 되 돌려 주 고 클 라 이언 트 에 게 https 로 요청 해 야 한다 고 알려 줍 니 다.
만약 우리 가 전체 항목 에서 사용 하려 고 한다 면, "WebAPIConfig" 클래스 에서 다음 과 같은 설정 을 하 십시오.
public static void Register(HttpConfiguration config)
   {
       config.Filters.Add(new ForceHttpsAttribute());
   }

만약 에 우리 가 상대 적 으로 구체 적 인 Controller 나 Action 설정 을 할 때 다음 과 같은 설정 을 할 수 있 습 니 다.
//    Controller    Https
[Learning.Web.Filters.ForceHttps()]
    public class CoursesController : BaseApiController
    {
    //          Https
        [Learning.Web.Filters.ForceHttps()]
            public HttpResponseMessage Post([FromBody] CourseModel courseModel)
            {
 
        }
}


Basic Authentication 을 사용 하여 사용 자 를 검증 합 니 다.
지금까지 저희 가 제공 한 모든 Api 는 공개 되 어 있 으 며 누구나 방문 할 수 있 습 니 다.그러나 정말 장면 에서 바람 직 하지 않다. 일부 데이터 에 대해 인증 을 통과 한 사용자 만 방문 할 수 있다. 우 리 는 여기 서 이 점 을 잘 설명 할 수 있다.
1. 클 라 이언 트 가 Get 요청 을 "http:// {your port} / api / students / {userName}" 로 보 낼 때. 예 를 들 어 상기 URI 를 통 해 userNme 를 "Taiseer Joudeh" 로 방문 합 니 다.의 정 보 를 제공 할 때 저 희 는 클 라 이언 트 에 게 Taiseer Joudeh 에 해당 하 는 사용자 이름과 비밀 번 호 를 제공 하도록 해 야 합 니 다. 검증 정 보 를 제공 하지 않 은 사용자 에 게 저 희 는 방문 하지 못 하 게 해 야 합 니 다. 왜냐하면 학생 정보 에는 중요 한 개인 정보 (email, birthday 등) 가 포함 되 어 있 기 때 문 입 니 다.
2. 클 라 이언 트 가 "http:// {your port} / api / courses / 2 / students / {userName}" 에 게 Post 요청 을 보 냈 을 때 이것 은 학생 들 에 게 수강 신청 을 하 는 것 을 의미 합 니 다. 여기 서 검증 을 하지 않 으 면 모든 사람 이 어떤 학생 에 게 마음대로 수강 신청 을 할 수 있다 면 혼 란 스 럽 지 않 겠 습 니까?
위의 장면 에 대해 저 희 는 Basic Authentication 을 사용 하여 인증 을 합 니 다. 주요 사 고 는 filter 를 사용 하여 헤더 부분 에서 신분 정 보 를 얻 고 인증 유형 이 'basic' 인지 확인 한 다음 에 내용 을 검증 하고 정확 하면 놓 습 니 다. 그렇지 않 으 면 401 (Unauthorized) 상태 코드 로 돌아 갑 니 다.
위 코드 전에 basic authentication 을 설명 하 십시오.
basic authentication 이란 무엇 입 니까?
이 는 Http 요청 을 본 격 적 으로 처리 하기 전에 요청 자의 신분 을 검증 하 는 것 을 의미 합 니 다. 이 는 서버 가 DoS 공격 (Denial of service attacks) 을 받 는 것 을 방지 할 수 있 습 니 다. 원 리 는 클 라 이언 트 가 Http 요청 을 보 낼 때 Header 부분 에 Base 64 인 코딩 을 기반 으로 한 사용자 이름과 비밀 번 호 를 제공 하 는 것 입 니 다. 'username: password', 메시지 수신 자 (서버) 입 니 다.검증 을 진행 하고 통과 후 요청 을 계속 처리 합 니 다.
사용자 이름과 비밀 번 호 는 base 64 인 코딩 만 적용 되 기 때문에 안전성 을 확보 하기 위해 basic authentication 은 보통 SSL 연결 (https) 을 기반 으로 합 니 다.
우리 api 에서 사용 하기 위해 서 "Learning AuthorizeAttribute" 를 만 들 고 System. Web. Http. Filters. AuthorizationFilterAttribute 에서 계승 합 니 다.
public class LearningAuthorizeAttribute : AuthorizationFilterAttribute
    {
 
        [Inject]
        public LearningRepository TheRepository { get; set; }
 
        public override void OnAuthorization(System.Web.Http.Controllers.HttpActionContext actionContext)
        {
            //forms authentication Case that user is authenticated using forms authentication
//so no need to check header for basic authentication.
            if (Thread.CurrentPrincipal.Identity.IsAuthenticated)
            {
                return;
            }
 
            var authHeader = actionContext.Request.Headers.Authorization;
 
            if (authHeader != null)
            {
                if (authHeader.Scheme.Equals("basic", StringComparison.OrdinalIgnoreCase) &&
                    !String.IsNullOrWhiteSpace(authHeader.Parameter))
                {
                    var credArray = GetCredentials(authHeader);
                    var userName = credArray[0];
                    var password = credArray[1];
 
                    if (IsResourceOwner(userName, actionContext))
                    {
                        //You can use Websecurity or asp.net memebrship provider to login, for
                        //for he sake of keeping example simple, we used out own login functionality
                        if (TheRepository.LoginStudent(userName, password))
                        {
                            var currentPrincipal = new GenericPrincipal(new GenericIdentity(userName), null);
                            Thread.CurrentPrincipal = currentPrincipal;
                            return;
                        }
                    }
                }
            }
 
            HandleUnauthorizedRequest(actionContext);
        }
 
        private string[] GetCredentials(System.Net.Http.Headers.AuthenticationHeaderValue authHeader)
        {
 
            //Base 64 encoded string
            var rawCred = authHeader.Parameter;
            var encoding = Encoding.GetEncoding("iso-8859-1");
            var cred = encoding.GetString(Convert.FromBase64String(rawCred));
 
            var credArray = cred.Split(':');
 
            return credArray;
        }
 
        private bool IsResourceOwner(string userName, System.Web.Http.Controllers.HttpActionContext actionContext)
        {
            var routeData = actionContext.Request.GetRouteData();
            var resourceUserName = routeData.Values["userName"] as string;
 
            if (resourceUserName == userName)
            {
                return true;
            }
            return false;
        }
 
        private void HandleUnauthorizedRequest(System.Web.Http.Controllers.HttpActionContext actionContext)
        {
            actionContext.Response = actionContext.Request.CreateResponse(HttpStatusCode.Unauthorized);
 
            actionContext.Response.Headers.Add("WWW-Authenticate",
                                               "Basic Scheme='eLearning' location='http://localhost:8323/account/login'");
 
        }
    }


"OnAuthorization" 을 다시 써 서 다음 과 같은 기능 을 실현 합 니 다.
1. Header 요청 에서 검사 데이터 가 져 오기
2. 인증 정보 유형 을 "basic" 로 판단 하고 base 64 인 코딩 포함
3. base 64 인 코딩 을 string 으로 바 꾸 고 사용자 이름과 비밀 번 호 를 추출 합 니 다.
4. 제 공 된 인증 정보 가 방문 한 자원 정보 와 같 는 지 확인 합 니 다 (학생 의 자세 한 정 보 는 그 가 직접 방문 할 수 있 습 니 다)
5. 데이터베이스 에 가서 사용자 이름과 비밀 번 호 를 확인 합 니 다.
6. 검증 이 통과 되면 Thread 의 Current Principal 을 설정 하여 다음 요청 이 모두 검증 을 통과 하도록 합 니 다.
7. 검증 이 통과 되 지 않 았 습 니 다. 401 (Unauthorized) 을 되 돌려 주 고 WWW - Authenticate 응답 헤드 를 추가 합 니 다. 이 요청 에 따라 클 라 이언 트 는 해당 하 는 인증 정 보 를 추가 할 수 있 습 니 다.
코드 에서 이 루어 지면 간단 합 니 다. 위의 Attribute 두 개 는 끝 입 니 다.
public class StudentsController : BaseApiController
    {
        [LearningAuthorizeAttribute]
        public HttpResponseMessage Get(string userName)
            {
 
            }
    }


public class EnrollmentsController : BaseApiController
    {
        [LearningAuthorizeAttribute]
        public HttpResponseMessage Post(int courseId, [FromUri]string userName, [FromBody]Enrollment enrollment)
            {
 
            }
    }


테스트 성과
테스트 도 구 를 사용 하여 다음 요청 을 보 냅 니 다:
ASP.NET Web Api 安全性_第2张图片
인증 을 제공 하지 않 았 기 때문에 다음 과 같은 응답 을 받 았 습 니 다.
ASP.NET Web Api 安全性_第3张图片
취소:
ASP.NET Web Api 安全性_第4张图片
데이터베이스 에서 해당 하 는 사용자 이름과 비밀 번 호 를 찾 아 입력 하면 다음 과 같은 결 과 를 얻 을 수 있 습 니 다.
ASP.NET Web Api 安全性_第5张图片
총결산
Base Authentication 은 안전성 이 떨 어 지지 만 쿠키 가 없 는 웹 Api 에 서 는 적용 이 매우 간단 하고 편리 하기 때문이다.
Base Authentication 의 가장 큰 단점 은 브 라 우 저 를 닫 을 때 까지 브 라 우 저 캐 시 되 어 있다 는 것 입 니 다. 만약 URI 에 대한 인증 을 받 았 다 면 브 라 우 저 는 권한 수여 헤 어 에 해당 하 는 증 거 를 보 내 서 크로스 사이트 에서 위조 요청 (CSRF) 공격 을 받 기 쉽 습 니 다.
Base Authentication 은 보통 HTTPS 방식 으로 암호 화 처 리 를 해 야 합 니 다.

좋은 웹페이지 즐겨찾기