학생 인증 붙이기
가입 폼에서 받은 학번과 비밀번호로 재학 여부를 확인하고, 학번·이름·학과만 가져옵니다. 비밀번호는 저장하거나 로그에 남기지 않습니다.
인증 흐름
섹션 제목: “인증 흐름”비밀번호가 틀리면 첫 실패에서 멈춥니다. 재시도가 없어서 라이브러리가 계정을 잠그지 않습니다.
요청 파라미터
섹션 제목: “요청 파라미터”필드 이름은 Python snake_case 기준이고, Node.js와 Java는 camelCase입니다. 포털 로그인이 필요합니다.
| 메서드 | 파라미터 | 타입 | 필수 | 기본값 | 설명 |
|---|---|---|---|---|---|
authenticate |
student_id |
문자열 | 예 | 학번 | |
password |
문자열 | 예 | 포털 비밀번호. 저장하거나 로그에 남기지 않음 | ||
include_raw |
boolean | 아니오 | false |
포털 원문(rawHtml, rawJson)도 받음 |
|
include_extra |
boolean | 아니오 | false |
학교가 주는 나머지 SIS 필드를 extra로 받음 |
|
authenticate_dhc |
student_id, password, include_raw |
학번·이름·학과·학년·학적 상태만 필요할 때 (연락처 조회 없이 더 가벼움) |
응답 데이터 구조
섹션 제목: “응답 데이터 구조”authenticate가 돌려주는 결과(위쪽)와 예시 함수가 가입 폼에 돌려주는 값(아래쪽)입니다. 필드 이름은 Python snake_case이고(student_id), Node.js와 Java는 camelCase(studentId, getStudentId())입니다. 값은 형태를 보여 주기 위한 가상의 예시입니다.
{ "success": true, "student_id": "20000000", "name": "홍길동", "major": "컴퓨터공학과", "grade": "3", "status": "재학", "email": "user@example.com", "phone_number": "010-0000-0000", "english_name": "Gildong Hong", "user_category": "학부생"}{ "verified": true, "student_id": "20000000", "name": "홍길동", "major": "컴퓨터공학과" }| 필드 | 의미 |
|---|---|
student_id / name / major |
학번 / 이름 / 학과(전공). 예시 함수가 돌려주는 값 |
status |
학적 상태 (재학, 휴학, 졸업 등). 포털 원문이라 표기가 바뀔 수 있음 |
grade |
학년 (문자열) |
email / phone_number / english_name / user_category |
연락처(SIS) 조회 결과. SIS 조회가 실패하면 null. 그 밖의 SIS 학교 코드 필드는 생략함 |
verified |
예시 함수가 status를 재학과 비교해 만든 값. 라이브러리 필드가 아님 |
전체 필드는 결과 필드를 보세요.
실패 시: 비밀번호 오류, 계정 잠김 등은 SejongAuthError(에러 코드 포함)로 던져집니다. 에러 코드
알아둘 점
섹션 제목: “알아둘 점”- 틀린 비밀번호를 반복해서 보내지 마세요. 포털이 계정을 잠급니다. 라이브러리는 첫 실패에서 멈추지만, 누구나 학번을 입력할 수 있는 폼이라면 학번별 실패 횟수를 제한하세요. 로그인 판정과 계정 잠금 방지
status,major는 포털의 원문 문자열입니다. 위재학비교는 예시이며, 표기가 바뀔 수 있으니 한 곳에 상수로 두세요.- 한 번의
authenticate는 연락처(SIS) 조회까지 포함합니다. 학번·이름·학과만 필요하면 DHC만 부르는authenticate_dhc/authenticateDhc/authenticateWithDHC가 더 가볍습니다. 결과 필드는 인증 메서드와 결과 필드를 보세요. - 서버에서만 호출하세요. 브라우저나 앱에서 직접 부르면 비밀번호가 제3자 코드에 노출됩니다.
- 분기는 메시지가 아니라 에러 코드로 합니다. 에러 코드
예시 코드
섹션 제목: “예시 코드”import kr.suhsaechan.sejongpeia.auth.model.SejongAuthResult;import kr.suhsaechan.sejongpeia.auth.service.SuhSejongAuthEngine;import kr.suhsaechan.sejongpeia.common.exception.SejongAuthErrorCode;import kr.suhsaechan.sejongpeia.common.exception.SejongAuthException;import org.springframework.stereotype.Service;
@Serviceclass StudentVerificationService {
private static final String ACTIVE_STATUS = "재학"; // 학교 원문 그대로 비교
private final SuhSejongAuthEngine sejongAuthEngine;
StudentVerificationService(SuhSejongAuthEngine sejongAuthEngine) { this.sejongAuthEngine = sejongAuthEngine; }
/** 학번, 이름, 학과만 돌려주고 비밀번호는 보관하지 않음 */ String verifySejongStudent(String studentId, String password) { try { SejongAuthResult result = sejongAuthEngine.authenticate(studentId, password); boolean isActiveStudent = ACTIVE_STATUS.equals(result.getStatus()); return isActiveStudent ? result.getName() + " (" + result.getMajor() + ")" : "재학생이 아닙니다"; } catch (SejongAuthException exception) { SejongAuthErrorCode errorCode = exception.getErrorCode(); if (errorCode == SejongAuthErrorCode.AUTHENTICATION_FAILED) { return "학번 또는 비밀번호가 틀렸습니다"; } if (errorCode == SejongAuthErrorCode.ACCOUNT_LOCKED) { return "포털 계정이 잠겼습니다. 포털에서 비밀번호를 재설정하세요"; } return "지금은 확인할 수 없습니다. 잠시 뒤 다시 시도하세요"; } }}from sejongpeia import authenticate, SejongAuthError, ErrorCode
ACTIVE_STATUS = "재학" # 학교 원문 문자열 그대로 비교 (포털 표기가 바뀌면 여기만 수정)
def verify_sejong_student(student_id: str, password: str) -> dict: """동아리 가입 시 학생 인증: 학번, 이름, 학과만 돌려주고 비밀번호는 보관하지 않음""" try: result = authenticate(student_id, password) except SejongAuthError as error: if error.code == ErrorCode.AUTHENTICATION_FAILED: return {"verified": False, "reason": "학번 또는 비밀번호가 틀렸습니다"} if error.code == ErrorCode.ACCOUNT_LOCKED: return {"verified": False, "reason": "포털 계정이 잠겼습니다. 포털에서 비밀번호를 재설정하세요"} if error.code == ErrorCode.INVALID_INPUT: return {"verified": False, "reason": "학번과 비밀번호를 입력하세요"} return {"verified": False, "reason": "지금은 확인할 수 없습니다. 잠시 뒤 다시 시도하세요"} # 연결, 파싱 등
return { "verified": result.status == ACTIVE_STATUS, "student_id": result.student_id, "name": result.name, "major": result.major, }import { authenticate, SejongAuthError, ErrorCode } from 'pro-sejongpeia';
const ACTIVE_STATUS = '재학'; // 학교 원문 문자열 그대로 비교 (포털 표기가 바뀌면 여기만 수정)
/** 동아리 가입 시 학생 인증: 학번, 이름, 학과만 돌려주고 비밀번호는 보관하지 않음 */export async function verifySejongStudent(studentId, password) { try { const result = await authenticate(studentId, password); return { verified: result.status === ACTIVE_STATUS, studentId: result.studentId, name: result.name, major: result.major }; } catch (error) { if (!(error instanceof SejongAuthError)) throw error; if (error.code === ErrorCode.AUTHENTICATION_FAILED) return { verified: false, reason: '학번 또는 비밀번호가 틀렸습니다' }; if (error.code === ErrorCode.ACCOUNT_LOCKED) return { verified: false, reason: '포털 계정이 잠겼습니다. 포털에서 비밀번호를 재설정하세요' }; if (error.code === ErrorCode.INVALID_INPUT) return { verified: false, reason: '학번과 비밀번호를 입력하세요' }; return { verified: false, reason: '지금은 확인할 수 없습니다. 잠시 뒤 다시 시도하세요' }; // 연결, 파싱 등 }}