CAS SSO עם אבטחת אביב

1. סקירה כללית

במדריך זה נבחן את שירות האימות המרכזי של Apereo (CAS) ונראה כיצד שירות Spring Boot יכול להשתמש בו לצורך אימות. CAS הוא פתרון Single Sign-On (SSO) ארגוני שהוא גם קוד פתוח.

מה זה SSO? כשאתה מתחבר ל- YouTube, Gmail ומפות עם אותם אישורים, זה כניסה יחידה. אנו נדגים זאת על ידי הגדרת שרת CAS ואפליקציית Spring Boot. אפליקציית Spring Boot תשתמש ב- CAS לאימות.

2. הגדרת שרת CAS

2.1. התקנת CAS ותלות

השרת משתמש בסגנון כיסוי מלחמה של Maven (Gradle) כדי להקל על ההתקנה והפריסה:

שיבוט git //github.com/apereo/cas-overlay-template.git שרת cas

פקודה זו תשבט את תבנית cas-overlay לתוך ה שרת cas מַדרִיך.

חלק מההיבטים שנעסוק בהם כוללים רישום שירות JSON וחיבור מסדי נתונים JDBC. אז נוסיף את המודולים שלהם ל- תלות חלק של build.gradle קוֹבֶץ:

הידור "org.apereo.cas: cas-server-support-json-service-registry: $ {casServerVersion}" הידור "org.apereo.cas: cas-server-support-jdbc: $ {casServerVersion}"

בואו נדאג לבדוק את הגרסה האחרונה של casServer.

2.2. תצורת שרת CAS

לפני שנוכל להפעיל את שרת CAS, עלינו להוסיף כמה תצורות בסיסיות. נתחיל ביצירת a cas-server / src / main / resources תיקייה ובתיקיה זו. לאחר מכן יצור application.properties גם בתיקיה:

server.port = 8443 spring.main.allow-bean-definition-overriding = true server.ssl.key-store = classpath: / etc / cas / thekeystore server.ssl.key-store-password = changeit

בואו נמשיך ביצירת קובץ מאגר המפתחות שהוזכר בתצורה לעיל. ראשית, עלינו ליצור את התיקיות / etc / cas ו / etc / cas / config ב cas-server / src / main / resources.

לאחר מכן, עלינו לשנות את הספרייה ל שרת cas / src / main / resources / etc / cas והפעל את הפקודה להפקה חנות המפתחות:

keytool -key -keyalg RSA -alias thekeystore-keystore thekeystore -storepass changeit -validity 360-key size 2048

על מנת שלא תהיה לנו שגיאת לחיצת יד SSL, עלינו להשתמש מארח מקומי כערך שם פרטי ושם משפחה. עלינו להשתמש בו גם עבור שם הארגון והיחידה. יתר על כן, עלינו לייבא את חנות המפתחות ל- JDK / JRE שנשתמש בה להפעלת אפליקציית הלקוח שלנו:

keytool -importkeystore -srckeystore thekeystore -destkeystore $ JAVA11_HOME / jre / lib / אבטחה / cacerts

הסיסמה למאגר המקורות והיעד היא שנה את זה. במערכות יוניקס, ייתכן שנצטרך להריץ פקודה זו עם admin (סודוזכות. לאחר הייבוא, עלינו להפעיל מחדש את כל המופעים של Java שמפעילים או להפעיל מחדש את המערכת.

אנו משתמשים ב- JDK11 מכיוון שהוא נדרש לפי CAS גרסה 6.1.x. כמו כן, הגדרנו את משתנה הסביבה $ JAVA11_HOME שמצביע על ספריית הבית שלו. כעת אנו יכולים להפעיל את שרת CAS:

./gradlew הפעל -Dorg.gradle.java.home = $ JAVA11_HOME

כאשר האפליקציה מתחילה, נראה את המסך "READY" והשרת יהיה זמין בכתובת // localhost: 8443.

2.3. תצורת משתמש שרת CAS

איננו יכולים להתחבר עדיין מכיוון שלא הגדרנו אף משתמש. ל- CAS יש שיטות שונות לניהול תצורה, כולל מצב עצמאי. בואו ניצור תיקיית תצורה שרת cas / src / main / resources / etc / cas / config בו ניצור קובץ מאפיינים נכסי cas. כעת, אנו יכולים להגדיר משתמש סטטי בקובץ המאפיינים:

cas.authn.accept.users = casuser :: מלון

עלינו לתקשר את מיקום תיקיית התצורה לשרת CAS כדי שההגדרות ייכנסו לתוקף. בואו נעדכן משימות.דרגה כדי שנוכל להעביר את המיקום כארגומנט JVM משורת הפקודה:

הפעלת משימות (קבוצה: "build", תיאור: "הפעל את יישום האינטרנט CAS במצב מיכל מוטבע") {תלוי על 'build' doLast {def casRunArgs = ArrayList new (Arrays.asList ("-server -noverify -Xmx2048M -XX: + TieredCompilation -XX: TieredStopAtLevel = 1 ".split (" "))) if (project.hasProperty ('args')) {casRunArgs.addAll (project.args.split ('\ s +'))} javaexec {main = "-jar" jvmArgs = casRunArgs args = ["build / libs / $ {casWebApplicationBinaryName}"] logger.info "התחיל $ {commandLine}"}}}

לאחר מכן אנו שומרים את הקובץ ומריצים:

./gradlew הפעל -Dorg.gradle.java.home = $ JAVA11_HOME -Pargs = "- Dcas.standalone.configurationDirectory = / cas-server / src / main / resources / etc / cas / config"

שים לב שהערך של cas.standalone.configurationDirectory היא דרך מוחלטת. עכשיו אנחנו יכולים ללכת ל // localhost: 8443 והיכנס באמצעות שם משתמש קזוזר וסיסמא מלון.

3. הגדרת לקוח CAS

נשתמש ב- Spring Initializr כדי ליצור אפליקציית לקוח Boot Boot. יהיה לזה אינטרנט, בִּטָחוֹן, סמן חופשי ו DevTools תלות. חוץ מזה, נוסיף גם את התלות של מודול Spring Security CAS pom.xml:

 org.springframework.security spring-security-cas 5.3.0.RELEASE 

לבסוף, בואו נוסיף את המאפיינים הבאים של אתחול האביב להגדרת האפליקציה:

server.port = 8900 spring.freemarker.suffix = .ftl

4. רישום שירות שרת CAS

יישומי לקוחות חייבים להירשם בשרת CAS לפני כל אימות. שרת CAS תומך בשימוש ברישומי לקוח YAML, JSON, MongoDB ו- LDAP.

במדריך זה נשתמש בשיטת רישום השירות של JSON. בואו ניצור תיקיה נוספת שרת cas / src / main / resources / etc / cas / services. זו התיקיה שתאכלס את קבצי ה- JSON של רישום השירות.

ניצור קובץ JSON המכיל את ההגדרה של יישום הלקוח שלנו. שם הקובץ, casSecuredApp-8900.json, עוקב אחר התבנית serviceName-Id.json:

{"@class": "org.apereo.cas.services.RegexRegisteredService", "serviceId": "// localhost: 8900 / login / cas", "name": "casSecuredApp", "id": 8900, "logoutType ":" BACK_CHANNEL "," logoutUrl ":" // localhost: 8900 / exit / cas "}

ה serviceId תכונה מגדירה דפוס URL של regex עבור יישום הלקוח. התבנית צריכה להתאים לכתובת האתר של יישום הלקוח.

ה תְעוּדַת זֶהוּת המאפיין צריך להיות ייחודי. במילים אחרות, לא צריכים להיות שני שירותים או יותר זהים תְעוּדַת זֶהוּת רשום לאותו שרת CAS. לאחר שכפול תְעוּדַת זֶהוּת יוביל לקונפליקטים ועקיפת תצורות.

אנו מגדירים גם את סוג ההתנתקות ערוץ אחורי ואת כתובת האתר שתהיה // localhost: 8900 / יציאה / cas כדי שנוכל לבצע כניסה יחידה מאוחר יותר. לפני ששרת CAS יוכל להשתמש בקובץ התצורה של JSON, עלינו לאפשר את הרישום JSON אצלנו נכסי cas:
cas.serviceRegistry.initFromJson = נכון cas.serviceRegistry.json.location = classpath: / etc / cas / services

5. תצורת כניסה יחידה של לקוח CAS

השלב הבא מבחינתנו הוא קביעת תצורה של Spring Security כך שתעבוד עם שרת CAS. עלינו לבדוק גם את זרימת האינטראקציות המלאה, הנקראת רצף CAS.

בואו נוסיף את תצורות השעועית הבאות ל- יישום CasSecured בכיתה של אפליקציית Spring Boot:

@Bean CasAuthenticationFilter casAuthenticationFilter ציבורי (AuthenticationManager authenticationManager, ServiceProperties serviceProperties) זורק חריג {CasAuthenticationFilter filter = new CasAuthenticationFilter (); filter.setAuthenticationManager (authenticationManager); filter.setServiceProperties (serviceProperties); מסנן החזרה; } @Bean ServiceProperties public ServiceProperties () {logger.info ("מאפייני שירות"); ServiceProperties serviceProperties = ServiceProperties חדש (); serviceProperties.setService ("// cas-client: 8900 / login / cas"); serviceProperties.setSendRenew (שקר); שירות החזרת נכסים; } @Bean TicketValidator ticketValidator () {החזר Cas30ServiceTicketValidator חדש ("// localhost: 8443"); } @ שעועית ציבורית CasAuthenticationProvider casAuthenticationProvider (TicketValidator ticketValidator, ServiceProperties serviceProperties) {CasAuthenticationProvider provider = new CasAuthenticationProvider (); provider.setServiceProperties (serviceProperties); provider.setTicketValidator (ticketValidator); provider.setUserDetailsService (s -> משתמש חדש ("[מוגן באמצעות דוא"ל]", "מלון", נכון, נכון, נכון, נכון, AuthorityUtils.createAuthorityList ("ROLE_ADMIN"))); provider.setKey ("CAS_PROVIDER_LOCALHOST_8900"); ספק החזר; }

ה מאפייני שירות לשעועית יש אותה כתובת אתר כמו serviceId ב casSecuredApp-8900.json. זה חשוב מכיוון שהוא מזהה לקוח זה לשרת CAS.

ה שלח חידוש רכוש של מאפייני שירות נקבע ל שֶׁקֶר. פירוש הדבר שמשתמש צריך להציג אישורי כניסה לשרת פעם אחת בלבד.

ה אימות כניסה שעועית תטפל בחריגים של אימות. לפיכך, זה ינתב את המשתמש לכתובת האתר של הכניסה של שרת CAS לצורך אימות.

לסיכום, זרימת האימות נמשכת:

  1. משתמש מנסה לגשת לדף מאובטח, שמפעיל חריג אימות
  2. החריג מפעיל אימות כניסה. בתגובה, אימות כניסה יעביר את המשתמש לדף הכניסה לשרת CAS - // localhost: 8443 / התחברות
  3. לאחר אימות מוצלח, השרת מפנה חזרה ללקוח באמצעות כרטיס
  4. CasAuthenticationFilter ירים את ההפניה מחדש ויתקשר CasAuthenticationProvider
  5. CasAuthenticationProvider אשתמש TicketValidator כדי לאשר את הכרטיס שהוצג בשרת CAS
  6. אם הכרטיס תקף, המשתמש יקבל הפניה לכתובת האתר המאובטחת המבוקשת

לבסוף, בואו להגדיר HttpSecurity כדי לאבטח כמה מסלולים ב WebSecurityConfig. בתהליך, נוסיף גם את נקודת כניסה לאימות לטיפול בחריגים:

תצורת הריקות המוגנת על ידי @Override (HttpSecurity http) זורקת חריג {http.authorizeRequests (). AntMatchers ("/ מאובטח", "/ כניסה"). מאומת () .and (). ExceptionHandling () .authenticationEntryPoint (authenticationEntryPoint ()); }

6. תצורת התנתקות אחת של לקוח CAS

עד כה עסקנו בכניסה יחידה; בואו ניקח בחשבון CAS כניסה יחידה (SLO).

יישומים המשתמשים ב- CAS לניהול אימות משתמשים יכולים להתנתק ממשתמש משני מקומות:

  • יישום הלקוח יכול להתנתק ממשתמש מעצמו באופן מקומי - זה לא ישפיע על מצב הכניסה של המשתמש ביישומים אחרים המשתמשים באותו שרת CAS.
  • יישום הלקוח יכול גם להתנתק מהמשתמש משרת CAS - זה יגרום למשתמש להתנתק מכל אפליקציות הלקוח האחרות המחוברות לאותו שרת CAS.

ראשית נכניס התנתקות ליישום הלקוח ואז נרחיב אותו להתנתקות בודדת בשרת CAS.

על מנת להבהיר מה קורה מאחורי הסצנה, ניצור להתנתק() שיטה לטיפול בהתנתקות המקומית. בהצלחה, זה ינתב אותנו לדף עם קישור להתנתקות יחידה:

@GetMapping ("/ logout") יציאת מחרוזת ציבורית (בקשת HttpServletRequest, תגובת HttpServletResponse, SecurityContextLogoutHandler logoutHandler) {Authentication auth = SecurityContextHolder .getContext (). GetAuthentication (); logoutHandler.logout (בקשה, תגובה, אימות); CookieClearingLogoutHandler חדש (AbstractRememberMeServices.SPRING_SECURITY_REMEMBER_ME_COOKIE_KEY) .logout (בקשה, תגובה, אימות); להחזיר "auth / logout"; }

בתהליך ההתנתקות היחיד, שרת ה- CAS יפוג תחילה את כרטיס המשתמש ואז ישלח בקשת async לכל אפליקציות הלקוח הרשומות. כל אפליקציית לקוח שתקבל אות זה תבצע התנתקות מקומית. בכך השגת מטרת ההתנתקות פעם אחת, היא תגרום להתנתקות בכל מקום.

עם זאת, בואו נוסיף כמה תצורות שעועית לאפליקציית הלקוח שלנו. באופן ספציפי, ב CasSecuredApplicaiton:

@Bean SecurityContextLogoutHandler ציבורי securityContextLogoutHandler () {להחזיר SecurityContextLogoutHandler חדש (); } @Bean LogoutFilter public logoutFilter () {LogoutFilter logoutFilter = LogoutFilter new ("// localhost: 8443 / logout", securityContextLogoutHandler ()); logoutFilter.setFilterProcessesUrl ("/ logout / cas"); החזרת logoutFilter; } @Bean ציבורי SingleSignOutFilter singleSignOutFilter () {SingleSignOutFilter singleSignOutFilter = חדש SingleSignOutFilter (); singleSignOutFilter.setCasServerUrlPrefix ("// localhost: 8443"); singleSignOutFilter.setLogoutCallbackPath ("/ יציאה / cas"); singleSignOutFilter.setIgnoreInitConfiguration (true); להחזיר singleSignOutFilter; }

ה logoutFilter יירט בקשות ל / יציאה / cas ולהפנות את היישום לשרת CAS. ה SingleSignOutFilter יירט בקשות המגיעות משרת CAS ויבצע את ההתנתקות המקומית.

7. חיבור שרת CAS לבסיס נתונים

אנו יכולים להגדיר את שרת ה- CAS לקרוא אישורים ממסד נתונים של MySQL. נשתמש ב- מִבְחָן מסד נתונים של שרת MySQL הפועל במחשב מקומי. בואו נעדכן שרת cas / src / main / resources / etc / cas / config / cas.properties:

cas.authn.accept.users = cas.authn.jdbc.query [0] .sql = בחר * ממשתמשים איפה דוא"ל =? cas.authn.jdbc.query [0] .url = jdbc: mysql: //127.0.0.1: 3306 / מבחן? useUnicode = true & useJDBCCompliantTimezoneShift = true & useLegacyDatetimeCode = false & serverTimezone = UTC cas.authn.jdbc.query [0] .dialect = org.hibernate.dialect.MySQLDialect cas.authn.jdbc.query [0] .user = root casb.auth. [0]. סיסמה = שורש cas.authn.jdbc.query [0] .ddlAuto = אין cas.authn.jdbc.query [0] .driverClass = com.mysql.cj.jdbc.Driver cas.authn.jdbc.query [0] .fieldPassword = סיסמה cas.authn.jdbc.query [0] .passwordEncoder.type = NONE

הגדרנו את cas.authn.accept.users לריק. זה יבטל את השימוש במאגרי משתמשים סטטיים על ידי שרת CAS.

על פי ה- SQL לעיל, אישורי המשתמשים מאוחסנים ב- משתמשים שולחן. ה אימייל העמודה היא המייצגת את מנהל המשתמשים (שם משתמש).

אנא הקפד לבדוק את רשימת מאגרי המידע הנתמכים, מנהלי ההתקנים והניבים הזמינים. הגדרנו גם את סוג מקודד הסיסמה ל- אף אחד. קיימים גם מנגנוני הצפנה אחרים ותכונותיהם המוזרות.

שים לב שהמנהל במסד הנתונים של שרת CAS חייב להיות זהה לזה של יישום הלקוח.

בואו נעדכן CasAuthenticationProvider שיהיה שם משתמש זהה לשרת CAS:

@Bean CasAuthenticationProvider ציבורי casAuthenticationProvider () {CasAuthenticationProvider provider = CasAuthenticationProvider חדש (); provider.setServiceProperties (serviceProperties ()); provider.setTicketValidator (ticketValidator ()); provider.setUserDetailsService (s -> משתמש חדש ("[מוגן באמצעות דוא"ל]", "מלון", נכון, נכון, נכון, נכון, AuthorityUtils.createAuthorityList ("ROLE_ADMIN"))); provider.setKey ("CAS_PROVIDER_LOCALHOST_8900"); ספק החזר; }

CasAuthenticationProvider אינו משתמש בסיסמה לצורך אימות. עם זאת, שם המשתמש שלו צריך להיות תואם לזה של שרת CAS כדי שהאימות יצליח. שרת CAS דורש שרת MySQL לפעול בו מארח מקומי בנמל 3306. שם המשתמש והסיסמה צריכים להיות שורש.

הפעל מחדש את שרת CAS ואת אפליקציית Spring Boot. לאחר מכן השתמש בתעודות החדשות לאימות.

8. מסקנה

בדקנו כיצד להשתמש ב- CAS SSO עם Spring Security ורבים מקבצי התצורה המעורבים. ישנם היבטים רבים אחרים של CAS SSO הניתנים להגדרה. החל בין נושאים וסוגי פרוטוקולים למדיניות אימות.

אלה ואחרים נמצאים במסמכים. קוד המקור של שרת CAS ואפליקציית Spring Boot זמין ב- GitHub.


$config[zx-auto] not found$config[zx-overlay] not found