CAS SSO med vårsikkerhet

1. Oversikt

I denne opplæringen ser vi på Apereo Central Authentication Service (CAS), og vi ser hvordan en Spring Boot-tjeneste kan bruke den til autentisering. CAS er en enterprise Single Sign-On (SSO) løsning som også er åpen kildekode.

Hva er SSO? Når du logger på YouTube, Gmail og Maps med samme legitimasjon, er det enkelt pålogging. Vi skal demonstrere dette ved å sette opp en CAS-server og en Spring Boot-app. Spring Boot-appen bruker CAS for autentisering.

2. Oppsett av CAS-server

2.1. CAS-installasjon og avhengigheter

Serveren bruker Maven (Gradle) War Overlay-stil for å lette oppsett og distribusjon:

git clone //github.com/apereo/cas-overlay-template.git cas-server

Denne kommandoen vil klone cas-overlay-mal inn i det cas-server katalog.

Noen av aspektene vi skal dekke inkluderer JSON-tjeneregistrering og JDBC-databaseforbindelse. Så, vi legger til modulene sine i avhengigheter seksjon av build.gradle fil:

kompilere "org.apereo.cas: cas-server-support-json-service-registry: $ {casServerVersion}" kompilere "org.apereo.cas: cas-server-support-jdbc: $ {casServerVersion}"

La oss sørge for å sjekke den nyeste versjonen av casServer.

2.2. CAS-serverkonfigurasjon

Før vi kan starte CAS-serveren, må vi legge til noen grunnleggende konfigurasjoner. La oss starte med å lage en cas-server / src / main / resources mappen og i denne mappen. Dette vil bli fulgt av opprettelsen av application.properties i mappen også:

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

La oss fortsette med opprettelsen av nøkkellagerfilen som det er referert til i konfigurasjonen ovenfor. Først må vi lage mappene / etc / cas og / etc / cas / config i cas-server / src / main / resources.

Deretter må vi endre katalogen til cas-server / src / main / resources / etc / cas og kjør kommandoen for å generere nøkkelbutikken:

nøkkelverktøy -genkey -keyalg RSA -alias thekeystore -keystore thekeystore -storepass changeit -validity 360 -keysize 2048

For at vi ikke skal ha en SSL-håndtrykkingsfeil, bør vi bruke lokal vert som verdien på for- og etternavn. Vi bør også bruke det samme for organisasjonsnavnet og enheten. Videre må vi importere nøkkelbutikken inn i JDK / JRE vi skal bruke til å kjøre klientappen vår:

keytool -importkeystore -srckeystore thekeystore -destkeystore $ JAVA11_HOME / jre / lib / security / cacerts

Passordet for kilde- og destinasjonsnøkkelbutikken er endre det. På Unix-systemer må vi kanskje kjøre denne kommandoen med admin (sudo) privilegium. Etter importen, bør vi starte alle forekomster av Java som kjører eller starte systemet på nytt.

Vi bruker JDK11 fordi det kreves av CAS versjon 6.1.x. Vi definerte også miljøvariabelen $ JAVA11_HOME som peker til hjemmekatalogen. Vi kan nå starte CAS-serveren:

./gradlew run -Dorg.gradle.java.home = $ JAVA11_HOME

Når applikasjonen starter, ser vi “KLAR” trykt på terminalen og serveren vil være tilgjengelig på // lokal vert: 8443.

2.3. CAS Server Brukerkonfigurasjon

Vi kan ikke logge på ennå, ettersom vi ikke har konfigurert noen brukere. CAS har forskjellige metoder for å administrere konfigurasjon, inkludert frittstående modus. La oss lage en konfigurasjonsmappe cas-server / src / main / resources / etc / cas / config der vi oppretter en eiendomsfil cas. eiendommer. Nå kan vi definere en statisk bruker i egenskapsfilen:

cas.authn.accept.users = casuser :: Mellon

Vi må kommunisere plasseringen til konfigurasjonsmappen til CAS-serveren for at innstillingene skal tre i kraft. La oss oppdatere oppgaver. gradere slik at vi kan overføre stedet som et JVM-argument fra kommandolinjen:

oppgaveløp (gruppe: "build", beskrivelse: "Kjør CAS-webapplikasjonen i innebygd beholdermodus") {henger på 'build' doLast {def casRunArgs = new ArrayList (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 "Startet $ {commandLine}"}}}

Vi lagrer deretter filen og kjører:

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

Vær oppmerksom på at verdien av cas.standalone.configurationDirectory er en absolutt vei. Vi kan nå gå til // lokal vert: 8443 og logg inn med brukernavn casuser og passord Mellon.

3. CAS-klientoppsett

Vi bruker Spring Initializr til å generere en Spring Boot-klientapp. Det får det Internett, Sikkerhet, Freemarker og DevTools avhengigheter. Dessuten vil vi også legge til avhengigheten for Spring Security CAS-modul til sin pom.xml:

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

Til slutt, la oss legge til følgende Spring Boot-egenskaper for å konfigurere appen:

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

4. CAS-serverregistrering

Klientsøknader må registrere seg hos CAS-serveren før autentisering. CAS-server støtter bruk av YAML-, JSON-, MongoDB- og LDAP-klientregister.

I denne opplæringen bruker vi JSON Service Registry-metoden. La oss lage enda en mappe cas-server / src / main / resources / etc / cas / services. Det er denne mappen som vil huse JSON-filene for tjenestregisteret.

Vi oppretter en JSON-fil som inneholder definisjonen av klientapplikasjonen vår. Navnet på filen, casSecuredApp-8900.json, følger mønsteret 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 "}

De serviceId attributt definerer et regex URL-mønster for klientapplikasjonen. Mønsteret skal samsvare med URL-adressen til klientapplikasjonen.

De id attributt skal være unikt. Med andre ord, det skal ikke være to eller flere tjenester med det samme id registrert på samme CAS-server. Å ha duplikat id vil føre til konflikter og overstyring av konfigurasjoner.

Vi konfigurerer også logout-typen til å være BACK_CHANNEL og nettadressen som skal være // localhost: 8900 / exit / cas slik at vi kan gjøre en enkelt avlogging senere. Før CAS-serveren kan bruke JSON-konfigurasjonsfilen vår, må vi aktivere JSON-registeret i vår cas. eiendommer:
cas.serviceRegistry.initFromJson = true cas.serviceRegistry.json.location = classpath: / etc / cas / services

5. CAS Client Single Sign-On Configuration

Det neste trinnet for oss er å konfigurere Spring Security til å fungere med CAS-serveren. Vi bør også sjekke hele strømmen av interaksjoner, kalt en CAS-sekvens.

La oss legge til følgende bønnekonfigurasjoner i CasSecuredApplication klasse av vår Boot Boot-app:

@Bean public CasAuthenticationFilter casAuthenticationFilter (AuthenticationManager authenticationManager, ServiceProperties serviceProperties) kaster Unntak {CasAuthenticationFilter filter = new CasAuthenticationFilter (); filter.setAuthenticationManager (authenticationManager); filter.setServiceProperties (serviceProperties); returfilter; } @Bean public ServiceProperties serviceProperties () {logger.info ("service egenskaper"); ServiceProperties serviceProperties = nye ServiceProperties (); serviceProperties.setService ("// cas-client: 8900 / login / cas"); serviceProperties.setSendRenew (false); retur tjeneste Eiendommer; } @Bean public TicketValidator ticketValidator () {return new Cas30ServiceTicketValidator ("// localhost: 8443"); } @Bean public CasAuthenticationProvider casAuthenticationProvider (TicketValidator ticketValidator, ServiceProperties serviceProperties) {CasAuthenticationProvider provider = new CasAuthenticationProvider (); provider.setServiceProperties (serviceProperties); provider.setTicketValidator (ticketValidator); provider.setUserDetailsService (s -> ny bruker ("[email protected]", "Mellon", true, true, true, true, AuthorityUtils.createAuthorityList ("ROLE_ADMIN"))); provider.setKey ("CAS_PROVIDER_LOCALHOST_8900"); returleverandør; }

De Tjenesteegenskaper bean har samme URL som serviceId i casSecuredApp-8900.json. Dette er viktig fordi den identifiserer denne klienten til CAS-serveren.

De sendRenew tilhører Tjenesteegenskaper er satt til falsk. Dette betyr at en bruker bare trenger å presentere påloggingsinformasjon til serveren en gang.

De AutentiseringEntryPoint bean håndterer unntak for godkjenning. Dermed vil det omdirigere brukeren til innloggings-URL til CAS-serveren for autentisering.

Oppsummert går autentiseringsflyten:

  1. En bruker prøver å få tilgang til en sikker side, som utløser et autentiserings unntak
  2. Unntaket utløser AutentiseringEntryPoint. Som svar, den AutentiseringEntryPoint tar brukeren til CAS-serverens påloggingsside - // localhost: 8443 / innlogging
  3. Ved vellykket autentisering omdirigerer serveren tilbake til klienten med en billett
  4. CasAuthenticationFilter vil hente viderekoblingen og ringe CasAuthenticationProvider
  5. CasAuthenticationProvider vil bruke TicketValidator for å bekrefte den presenterte billetten på CAS-serveren
  6. Hvis billetten er gyldig, vil brukeren få en omdirigering til ønsket sikker URL

Til slutt, la oss konfigurere HttpSikkerhet for å sikre noen ruter i WebSecurityConfig. I prosessen vil vi også legge til autentiseringsinngangspunktet for unntakshåndtering:

@ Override beskyttet ugyldig konfigurering (HttpSecurity http) kaster Unntak {http.authorizeRequests (). AntMatchers ("/ secure", "/ login") .autentisert () .and (). ExceptionHandling () .authenticationEntryPoint (authenticationEntryPoint ()); }

6. Konfigurasjon av CAS-klient for enkeltlogg

Så langt har vi jobbet med single sign-on; la oss nå vurdere CAS single logout (SLO).

Applikasjoner som bruker CAS for å administrere brukerautentisering, kan logge ut en bruker fra to steder:

  • Klientapplikasjonen kan logge ut en bruker fra seg selv lokalt - dette vil ikke påvirke brukerens påloggingsstatus i andre applikasjoner som bruker samme CAS-server
  • Klientapplikasjonen kan også logge ut brukeren fra CAS-serveren - dette vil føre til at brukeren blir logget ut fra alle andre klientapper som er koblet til samme CAS-server.

Vi setter først på plass avlogging på klientapplikasjonen og utvider den til en enkelt utlogging på CAS-serveren.

For å tydeliggjøre hva som skjer bak scenen, oppretter vi en Logg ut() metode for å håndtere den lokale avloggingen. Når det lykkes, vil det omdirigere oss til en side med en lenke for enkel utlogging:

@GetMapping ("/ logout") public Strenglogout (HttpServletRequest request, HttpServletResponse response, SecurityContextLogoutHandler logoutHandler) {Authentication auth = SecurityContextHolder .getContext (). GetAuthentication (); logoutHandler.logout (forespørsel, svar, godkjenning); ny CookieClearingLogoutHandler (AbstractRememberMeServices.SPRING_SECURITY_REMEMBER_ME_COOKIE_KEY) .logout (forespørsel, svar, godkjenning); returner "auth / logout"; }

I den eneste utloggingsprosessen utløper CAS-serveren først brukerens billett og sender deretter en asynkroniseringsforespørsel til alle registrerte klientapper. Hver klientapp som mottar dette signalet vil utføre en lokal avlogging. Ved å oppnå målet om avlogging en gang, vil det føre til en utlogging overalt.

Når det er sagt, la oss legge til noen bønnekonfigurasjoner i klientappen vår. Spesielt i CasSecuredApplicaiton:

@Bean public SecurityContextLogoutHandler securityContextLogoutHandler () {return new SecurityContextLogoutHandler (); } @Bean offentlig LogoutFilter logoutFilter () {LogoutFilter logoutFilter = new LogoutFilter ("// localhost: 8443 / logout", securityContextLogoutHandler ()); logoutFilter.setFilterProcessesUrl ("/ logout / cas"); retur logoutFilter; } @Bean offentlig SingleSignOutFilter singleSignOutFilter () {SingleSignOutFilter singleSignOutFilter = ny SingleSignOutFilter (); singleSignOutFilter.setCasServerUrlPrefix ("// localhost: 8443"); singleSignOutFilter.setLogoutCallbackPath ("/ exit / cas"); singleSignOutFilter.setIgnoreInitConfiguration (true); returner singleSignOutFilter; }

De logoutFilter vil avskjære forespørsler til / logout / cas og omdirigere applikasjonen til CAS-serveren. De SingleSignOutFilter vil avlytte forespørsler som kommer fra CAS-serveren og utføre den lokale utloggingen.

7. Koble CAS-serveren til en database

Vi kan konfigurere CAS-serveren til å lese legitimasjon fra en MySQL-database. Vi bruker test database til en MySQL-server som kjører på en lokal maskin. La oss oppdatere cas-server / src / main / resources / etc / cas / config / cas.properties:

cas.authn.accept.users = cas.authn.jdbc.query [0] .sql = VELG * FRA brukere HVOR e-post =? cas.authn.jdbc.query [0] .url = jdbc: mysql: //127.0.0.1: 3306 / test? useUnicode = true & useJDBCCompliantTimezoneShift = true & useLegacyDatetimeCode = false & serverTimezone = UTC cas.authn.jdbc.query [0] .dialect = org.hibernate.dialect.MySQLDialect cas.authn.jdbc.query [0] .bruker = root cas.auth. [0] .passord = rot cas.authn.jdbc.query [0] .ddlAuto = ingen cas.authn.jdbc.query [0] .driverClass = com.mysql.cj.jdbc.Driver cas.authn.jdbc.query [0] .fieldPassword = passord cas.authn.jdbc.query [0] .passwordEncoder.type = INGEN

Vi setter cas.authn.accept.users å blanke. Dette vil deaktivere bruken av statiske brukerregister av CAS-serveren.

I henhold til SQL ovenfor lagres brukernes legitimasjon i brukere bord. De e-post kolonnen er det som representerer brukernes rektor (brukernavn).

Sørg for å sjekke listen over støttede databaser, tilgjengelige drivere og dialekter. Vi setter også passordkodertypen til INGEN. Andre krypteringsmekanismer og deres særegne egenskaper er også tilgjengelige.

Merk at rektor i databasen til CAS-serveren må være den samme som klientapplikasjonen.

La oss oppdatere CasAuthenticationProvider å ha samme brukernavn som CAS-serveren:

@Bean public CasAuthenticationProvider casAuthenticationProvider () {CasAuthenticationProvider provider = new CasAuthenticationProvider (); provider.setServiceProperties (serviceProperties ()); provider.setTicketValidator (ticketValidator ()); provider.setUserDetailsService (s -> ny bruker ("[email protected]", "Mellon", true, true, true, true, AuthorityUtils.createAuthorityList ("ROLE_ADMIN"))); provider.setKey ("CAS_PROVIDER_LOCALHOST_8900"); returleverandør; }

CasAuthenticationProvider bruker ikke passordet for autentisering. Ikke desto mindre må brukernavnet samsvarer med CAS-serverens for at autentisering skal lykkes. CAS-server krever at en MySQL-server kjører lokal vert i havn 3306. Brukernavnet og passordet skal være rot.

Start CAS-serveren og Spring Boot-appen på nytt. Bruk deretter de nye legitimasjonene for autentisering.

8. Konklusjon

Vi har sett på hvordan du bruker CAS SSO med Spring Security og mange av de involverte konfigurasjonsfilene. Det er mange andre aspekter av CAS SSO som kan konfigureres. Alt fra temaer og protokolltyper til autentiseringsretningslinjer.

Disse og andre er i dokumentene. Kildekoden for CAS-serveren og Spring Boot-appen er tilgjengelig på GitHub.


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