보안 제한으로 인해 서비스가 null을 반환하거나 예외를 throw해야합니까? [닫은]


11

이 문제에 대해 더 숙련 된 개발자와 약간 의견이 다르며 다른 사람들이 이에 대해 어떻게 생각하는지 궁금합니다. 우리의 환경은 Java, EJB 3, 서비스 등입니다.

내가 작성한 코드는 물건을 얻고 물건을 만드는 서비스를 호출합니다. 내가 겪었던 문제는 의미가없는 null 포인터 예외가 있다는 것입니다. 예를 들어, 서비스에 객체 생성을 요청하면 null이 반환됩니다. 알려진 유효한 ID를 가진 객체를 찾으려고하면 null이 반환됩니다. 나는 내 코드에서 무엇이 잘못되었는지 알아 내려고 노력했다. 경험이 적기 때문에 일반적으로 내가 잘못한 것으로 가정하지만 null 반환의 이유는 보안이었습니다. 내 서비스를 사용하는 사용자 주체가 대상 서비스에 대한 올바른 권한을 가지고 있지 않은 경우 단순히 null을 반환합니다. 여기에있는 대부분의 다른 서비스는 잘 문서화되어 있지 않으므로 분명히 알아야 할 것입니다.

이는 서비스와 상호 작용하는 코드를 작성하는 개발자로서 혼동됩니다. 서비스가 사용자에게이 작업을로드하거나 해당 작업을 생성 할 수있는 적절한 권한이 없다는 것을 알려주는 예외가 있다면 훨씬 더 이해가 될 것입니다. 그런 다음 서비스가 예상대로 작동하지 않는 이유를 즉시 알 수있었습니다.

서비스를 작성한 숙련 된 개발자는 데이터를 요청하는 것은 오류 조건이 아니며 사용자가 데이터에 액세스 할 수없는 경우가 아니라 오류 조건에서만 예외를 처리해야한다고 주장했습니다. 이 데이터는 종종 GUI에서 조회되며 올바른 권한이없는 사용자의 경우 이러한 것들은 단순히 "존재하지 않습니다". 요컨대, 묻는 것은 잘못이 아니므로 예외는 아닙니다. 해당 사용자에게 "존재하지 않는"항목이 있으므로 Get 메소드는 널을 리턴합니다. 사용자가 해당 항목을 만들 수 없으면 Create 메서드는 null을 반환합니다.

이것이 정상적이거나 좋은 습관입니까? 나는 무슨 일이 일어나고 있는지 훨씬 쉽게 알기 때문에 예외를 사용하는 것을 선호합니다. 따라서 예를 들어 null을 반환하지 않고 잘못된 ID를 가진 객체를 요청한 경우 NotFoundException을 throw하는 것이 좋습니다.



@ChrisF : 1) 사람들이 null 참조를 줄이는 것에 관한 것입니다. 많은 경우에 그들은 적절하며, 나는 그들이 이것에 있다고 생각하지 않습니다. 2) 매개 변수를 확인하는 것과 관련이 있으며 예외를 던지는 것과 같은 종류의 결과가 아닌가? 3) 예외와 오류 코드는 문제가 무엇인지 "보여주는"방법이므로 다른 문제입니다. 예를 들어 예외를 지원하지 않는 시스템에 알려야하거나 최종 사용자가 코드 이외의 것을 보지 못하게하려면 오류 코드가 적합합니다.
Svish

여기서 내가 묻는 문제는 "무엇이 존재하지 않거나 발생하지 않은 척"대 "무엇이 존재하지 않거나 발생하지 않은 이유를 말하는 것"에 관한 것입니다.
Svish

3
나는 그것들이 중복되었다고 제안하지 않았습니다. 단지 그들이 당신에게 유용한 정보를 가지고있을뿐입니다.
ChrisF

사실, 미안합니다! 어떤 이유로 "아마도 가능한 복제본"주석으로 사용했을 것입니다. 아마도 수면 부족으로 인해 hehe.
Svish

답변:


19

예외는 오류가 있고 사물을 요청하는 것이 오류가 아닌 경우에만 발생합니다.

요청하는 것은 오류가 아닐 수 있지만 요청한 것에 대한 권한이없는 것은 일종의 오류입니다. 예외는 예외 조건을보고하는 특별한 방법으로, 특수 반환 값 대신 사용됩니다 (예 : null작성한대로 상황이 잘못 될 수있는 1 가지 이상의 이유가있을 경우 전혀 도움이되지 않음) 정확히 1 가지 가능한 이유, 다음 버전에서는 2 가지 이유가있을 수 있습니다. 따라서 null실패를 나타내는 반환 값으로 사용 하면 문제가 발생합니다.) 서비스가 원하는 방식으로 서비스를 제공하지 않는 이유를보고하지 않으면 설계가 잘못되었습니다.

특수 반환 값을 사용할지 여부 (예 : 음의 정수는 일반적으로 음이 아닌 정수를 반환하는 함수에 유용합니다), 예외, 전역 오류 처리기 또는 로거 등은 결국 구현 세부 사항입니다. 선택은 언어, 상황, 컨벤션에 따라 다르며 맛의 문제이기도합니다. 주요 포인트는이 있어야한다는 것입니다 몇 가지 알아내는 직접적인 방법 뭔가가 작동하지 않습니다. 그렇지 않으면 유일한 옵션은 다른 옵션으로 쓰레기를 버리는 것입니다. 블랙 박스의 동작과 어떤 관련이 있는지 알아내는 것은 시간 낭비입니다.

String.substring()IndexOutOfBoundsException인덱스가 범위를 벗어나 면를 던집니다 . 나는 복귀에 어떤 이점이 생각할 수 없다 null철학적 - -에도 불구하고, 대신 하나가이 주장 할 수 String는 경계 밖에 아무것도 포함하지 않는, 그래서 null다음 논리적 반환 값을 것입니다. 논리적 철학적이며 실용적이라는 것은 분명히 두 가지 다른 동물입니다.


substring ()이 범위를 벗어난 인덱스 값을 반환 할 경우 인덱스 사이의 문자열 부분을 반환해야합니다. 비어있을 수 있습니다. 호출 코드에서 테스트를 저장할 수 있습니다.
케빈 클라인

2
예, 끝이없는 "빈 값"과 null-토론이 있습니다. 범위를 벗어난 인덱스의 하위 문자열이 null이거나 빈 문자열이어야합니까? 나는 둘 다 효과적으로 "아무것도"(빈 문자열보다 "아무것도 아닌가?")지만, 예외가하는 정보량을 제공하지는 않는다.
Joonas Pulakka

@ kevincline : null 참조가 빈 문자열을 나타내는 관용적 수단 인 프레임 워크를 사용하지 않는 한 null 참조 substring를 반환 할 근거가 없습니다 . IMHO에는 두 가지 별도의 함수가 있어야합니다. 그 중 하나는 요청 된 문자 수를 반환하거나 예외를 throw하고 다른 하나는 최대한 많이 반환합니다. 일부 상황에서는 각 방법이 다른 방법보다 훨씬 우수합니다.
supercat

@ supercat : null을 반환하는 것에 대해 아무 말도하지 않았습니다. 나는 '반환 ... 부분 ... 아마도 비어있다'고 말했다. 빈 문자열은 Oracle을 제외하고는 null이 아닙니다.
케빈 클라인

@JoonasPulakka : 이전 의견에 핑을했을 것입니다.
supercat

5

그것은 계약이 무엇인지에 달려 있습니다. 계약서에 존재하지 않는 것을 요청할 수 있다고 말하면 어떤 일이 발생하는지 (널 또는 널 오브젝트) 말해야합니다.

반면, 계약서에 먼저 다른 메소드 DoesSomethingExist()를 호출 ( ) 한 다음 Get메소드 를 호출해야 한다고 명시되어 있으면 계약은 존재하는 것만 가져올 수 있고 그렇지 않은 경우 예외를 던질 수 있다고 말할 수 있습니다. 예외 메시지 DoesSomethingExist()는 유용한 오류 메시지 인 "먼저 호출해야합니다"와 같은 메시지를 표시 할 수 있습니다.


이 경우 존재하지 않는 ID를 요청하지 않기 때문에 존재하지 않는 것을 요청하는 것이 정상이 아니라고 말하고 싶습니다. 일반적으로 먼저 목록을 얻은 다음 자세한 내용을 보려면 특정 목록을 찾으십시오. 따라서 findAllThings메서드가 있다면 볼 수없는 일부 또는 모든 항목이있는 경우 빈 목록이나 하위 집합을 반환하는 것이 적절하다고 말합니다. 같은 방식으로 블로그에서 현재 사용자에게 속한 편집 용 게시물 만 나열 할 수 있습니다. 그러나 해당 사용자가 URL을 조정하고 다른 게시물을 편집하려고하면 ...
Svish

4

질문에 대한 하나의 크기에 맞는 답은 없습니다. 예외 사용 여부 또는 null 반환 여부는 상황에 따라 다릅니다.

이것을 교의적인 관점에서 순수하게 보지 말고 사용자 인터페이스로 인터페이스를보십시오 . 사용자 인터페이스를 사용할 있어야합니다 . 따라서 무언가를하는 "올바른"방법에 대한 자신의 의견에 상관없이 인터페이스를 사용하는 사람의 관점에서 가장 유용한 방법을 선택하십시오.

호출자가 오브젝트가 리턴되지 않는 이유를 알아야하는 경우 예외가 적절합니다. 그러나 일반적인 개념이 "권한이 없으면 존재하지 않는 경우"인 경우 널이 허용됩니다.

특히 귀하의 경우 발신자가 서버에 로그인하거나 서버에 연결 해야하는 경우 항목을 조회하는 데 null이 완벽하게 허용됩니다. 그때 당신은 당신이 허락을받지 않았다는 말을들을 것입니다. 게이트를 지나면 볼 수있는 권한이없는 (또는 존재한다는 것을 알 수없는) 무언가를 검색 할 때 null을 얻는 것이 합리적입니다.

반면에 초기 연결 또는 로그인 단계가없는 경우 예외가 적합합니다. 호출자가 항목이 존재한다는 것을 알고 다시 가져 오지 못하면 API는 null을 반환하는 데 도움이되지 않습니다.

그러나 아이템을 만들려면 다른 이야기입니다. 아마도 권한, 잘못된 매개 변수, 서버 메모리 부족 등이 실패하는 데에는 많은 이유가있을 수 있습니다. 개발자에게 이러한 모든 조건에 대해 null이 부여되면 적절한 조치를 결정할 방법이 없습니다. .

따라서 질문에 대답하려면 서비스를 사용하는 사람의 관점에서 가장 유용한 솔루션이 무엇인지 자문하십시오. 당신 이 그것을 사용 하는 방식 이 비정형 적 일 수 있으며 가장 일반적인 경우 null이 정답입니다.

따라서이 문제에 대한 종교적 전쟁에 참여하지 말고이 특정한 문제에 적합한 것을 결정하십시오.


이것에 대해 전투 장비를 착용 할 계획은 없습니다. 내가 생각하고 있던 것을 생각하는 데 내가 완전히 틀렸다는 것을 알고 궁금했다. 배우고 싶지만 한 사람이 그렇게 말했기 때문에 무언가를 뛰어 넘는 것을 좋아하지 않습니다. 특히 그것이 내 자신의 경험과 논리에 어긋나는 경우에는 (아무리 작더라도) 아닙니다. 어쨌든, 나는 이것이 최종 사용자 인터페이스라면 실제로 의미가 있음에 전적으로 동의합니다. 이것이 내가 아는 한, 코드 만 액세스 할 수 있습니다, 빈이기 때문에, 나는, 개발자로서, 말할 것 입니다 사용자.
Svish

1
그리고 개발자로서 나는 최종 사용자가 무엇을 알아야하는지에 관계없이 왜 문제가 있는지 걱정합니다.
Svish

Bryan과 완전히 동의합니다. 개발자조차도 다른 개발자 코드를 소비하는 사용자입니다. throw 또는 null의 결정은 특정 작업에 도움이되는 일종의 인터페이스 / gui입니다. 논리 나 철학의 일반적인 용어 만이 아닙니다.
독립적 인

3

나는 그것이 나쁜 디자인 이라고 생각합니다 . 널 포인터는 올바른 대답이 아니며 관리하기 까다로울 수 있습니다.

사용자가 적절한 자격 증명없이 서비스를 연결하려고하면 명확하고 간결한 답변으로 답변해야합니다. 대답은 예외 또는 특수 객체 일 수 있지만 null은 아닙니다.

네트워크 링크가 끊어 지거나 기타 예상치 못한 심각한 오작동이 발생하면 널 응답을 남겨 두어야합니다.

또한 왜 null을 얻었는지 이해하는 데 시간이 걸립니다. 모든 코드는 이해하기 쉽고 사용하기 쉬워야합니다. 널값을 갖는 것은 아닙니다.


마지막 문장에서 " 네트워크 링크가 끊어진 경우에만 null을 반환해야합니다. "라는 의미 입니까? 또는 " 네트워크 링크가 끊어지면 널 리턴을 중지해야합니다 ." ?
Péter Török

@Peter Török : "return null;"을 명시 적으로 사용하지 않는 것이 좋습니다. 그러나 주요 고장이 발생하면 일부 서비스에서 null을 반환하는 것이 허용됩니다.
아민

예기치 않은 중대한 오작동이 발생한 경우 예외가 더 적절하지 않습니까?
Svish

2
@ Amine : 그것이 null을 반환 하는 가장 적절한 경우 라고 말하고 싶습니다 .
Michael Borgwardt

@Svish : 주요 고장을 감지 할 수 있다면 물론 예외가 될 것입니다.
아민

3

좋은 소프트웨어 디자인을 염두에두고 프로젝트 수명을 생각해야합니다. 말한
대로을 반환 null하면 고객에게 정보를 제공하지 않습니다. 당신에게 무슨 일이 있었는지 처음에 문제가 어디에 있는지 몰랐습니다. 또한 문서가 제공되지 않으면 엉망입니다.

예외를 던져서 무엇이 잘못되었는지 알 수 있습니다. 원하는 경우 표시된 텍스트를보다 구체적으로 사용자 지정할 수도 있습니다.

반면에 돌아 null오면 클라이언트가 무슨 일이 일어나고 있는지 조사하게됩니다.

또한, 다른 곳에있어 문제가 있음을 깨달았습니다 NullPointerException. 이제 그 함수의 반환을 저장하지 않는다고 상상해보십시오 ... if else블록 으로 해당 함수에 대한 각 호출을 둘러싸 야합니다 ...

내 관점에서 돌아 오는 null것은 나쁜 습관이다.


2

서비스를 작성한 숙련 된 개발자는 데이터를 요청하는 것은 오류 조건이 아니며 사용자가 데이터에 액세스 할 수없는 경우가 아니라 오류 조건에서만 예외를 처리해야한다고 주장했습니다.

제 관점에서 이것은 말이되지 않습니다.

권한 없는 데이터를 쿼리 하면 적절한 액세스 권한이 없으면 예기치 않은 결과 가 발생하여 결과를 얻지 못 하므로 예외가 발생 합니다.

유추 : GET권한이없는 응답 코드 는 200 ok데이터 가 없으며 실제로 401 Unauthorized입니다.


1

null을 반환하는 것은 좋지 않습니다. 아무 것도 말해주지 않습니다. 예를 들어, 앱이 무언가를 찾으려고 시도하고 보안 문제 모두에 대해 응답이 null이고 항목이 존재하지 않으면 두 가지의 차이점을 어떻게 알 수 있습니까?

응용 프로그램이 의미있는 응답을 통해 다음에 수행 할 작업 또는 문제 해결 방법에 대한 논리적 선택을 할 수 있습니다.


개체가없는 것과 개체를 볼 수있는 권한이없는 경우의 차이점을 어떻게 알 수 있습니까? 아마도 시스템의 디자인은 당신이 모르는 것을 요구할 것입니다. 이 경우에는 답변 할 정보가 충분하지 않다고 생각하며 모든 경우에 적합한 답변은 없습니다. 당신이 그것을 볼 수 없다면 그것이 실제로없는 완벽한 사용 사례가 있습니다. 그리고 만약 당신이 그것을 볼 수 없다면 당신이 왜 할 수 없는지에 대한 예외가 주어져야하는 유스 케이스가 있습니다.
Bryan Oakley

"시스템을 설계하려면 모르는 것이 필요하다"는 것은 무엇을 의미합니까? 어떤 종류의 디자인이 될 수 있습니까?
Svish

2
보안 정책에 따라 볼 수 없다고 표시되는 경우 대부분의 경우 해당 정책이 존재하는지 알 수 없습니다. "찾을 수 없음"을 완벽하게 허용합니다.
Blrfl

1

근본 원인이 인증되지 않은 사용자 인 경우 pretty-message-page (및 관심있는 사람에게 알림)로 리디렉션되는 하드 HTTP 401 응답을 선호합니다. 승인 관련 원인은 사례별로 다릅니다. HTTP 응답 (403)을 반환하는 인수와 서비스 응답에 올바른 형식의 코드 / 메시지를 반환하는 인수가 있습니다.

예외는 예외적 인 상황에서만 사용해야하며 문제가 발생했음을 의미합니다. "허용되지 않음"을 의미하기 위해 오버로드되어야한다는 데 동의합니다. (널 리턴 값도 마찬가지입니다. "허용되지 않음"을 의미하는 데 동의하지 않습니다.)


글쎄, GUI 에서이 작업을 수행 할 수 있지만 장면 뒤에서 작업을 수행하는 서비스를 구현하는 Bean의 경우 예외와 특별한 반환 값 만 사용할 수 있습니다. 물론 사용자가 예외를 받아야한다는 것을 의미하지는 않지만 예를 들어 웹 서비스 / 서블릿 / 무엇이든간에 예외가 발생하여 적절한 것을 수행 할 수 있습니다. 어딘가, 하드 http 4xx 페이지 또는 다른 것으로 리디렉션하십시오.
Svish

좋은 지적이지만 이러한 사례를 포착하기 위해 AOP와 같은 패러다임을 사용할 수 있습니다. Aspect는 주어진 오퍼레이션을 호출하고 리다이렉트 / 허용 처리를 계속해서 수행 할 수있는 권한을 테스트 할 수 있습니다.
Mark

0

악마를 옹호하기 위해 널 돌려주는 편을 시도 할 것이다.

제 생각에는 이런 종류의 대응이 거의 수용 가능한 상황이며,이 경우와 같이 보안이 관련된 경우가 있습니다.

권한이없는 사람이 알 수없는 시스템 세부 정보를 실수로 제공하는 것은 매우 쉽습니다. 이것은 피해야합니다.

예를 들어, 사용자 이름 및 비밀번호 검사기를 사용하십시오. 별도의 오류 코드로 "사용자 이름을 찾을 수 없음"오류와 "잘못된 암호"오류를 반환하면 누군가 먼저 유효한 사용자 이름을 찾은 다음 암호를 찾을 수 있으므로 심각한 보안 문제가 발생할 수 있습니다. 일반적인 "잘못된 사용자 이름 / 암호"를 반환하는 것이 더 좋습니다.

따라서이 특별한 경우에 나는 돌아 오는 것이 거의 괜찮다고 말하고 싶지만 null, 함께 일하는 것은 매우 불쾌 할 것입니다.


예, 동의하지 않습니다. 내 의견으로는 적절한 응답은 예외이지만 사용자 이름을 찾을 수없고 비밀번호가 틀린 경우 모두 동일합니다. FailedToLogin, InvalidCredentials 등
Svish

@Svish-그러나 실패의 이유에 대한 힌트를 전혀주지 않으려는 경우 반환 null은 가장 도움이되지 않는 응답입니다. 시스템에 대한 무언가를 발견하기 위해 다른 어떤 것도 잠재적으로 사용될 수 있습니다. OP가 불만을 제기 한 이유는 null반환이 도움이되지 않은 내용을 설명 하지 않았기 때문 입니다. 의도적 인 목표는 즉 ... 절대적으로 말할 것도없고 하고 인정합니다. 내 관점에서 임무가 달성되었습니다.
OldCurmudgeon

글쎄, 그럴 수도 있지만, 여전히 그렇게하는 것이 좋지 않다고 말하고 싶습니다. 적어도 시스템 내부. 최종 사용자가 물건을 보는 가장자리에서 나는 동의 할 것입니다. 그러나 시스템 내부에서 개발자는 사용자이며, 왜 세상에서 우리 자신을 더 혼란스럽게 만들고 싶습니까? 마치 소프트웨어 개발이 충분히 어렵지 않은 것처럼 ...
Svish

1
그리고 로그인 예제, 나는 적어도 말의에서하지에 대한 사용자 경험을위한 그것의 나쁜 말하고 싶지만 뭔가 아무것도 그들이 (그들이 생각) 할 때 일어난 것 같았다 이유에 대한 자격 증명을 입력했습니다. 페이지가 새로 고쳐지고 로그인 시도를 무시한 것처럼 보이면 입력 한 내용이 아니라 시스템에 문제가 있다고 가정합니다.
Svish

-2

클라이언트 가이 메소드를 호출하고 null을 반환 할 때 return null이 비우호적이라고 생각합니다. 클라이언트는 발생한 상황과 왜 null을 반환했는지 알지 못합니다. 따라서 우리는 의미가있는 execption을 던져야하고이 execption을 설명하는 문서를 제공해야합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.