Autentifikacija pomoću Reddit OAuth2 i Spring Security
1. Pregled
U ovom uputstvu koristit ćemo Spring Security OAuth za autentifikaciju pomoću Reddit API-ja.
2. Konfiguracija Maven
Prvo, da bismo koristili Spring Security OAuth - moramo dodati sljedeću ovisnost o našoj pom.xml (naravno uz bilo koju drugu ovisnost o proljeću koju biste mogli koristiti):
org.springframework.security.oauth spring-security-oauth2 2.0.6.OBLAŽENJE
3. Konfigurirajte OAuth2 klijenta
Dalje - konfigurirajmo naš OAuth2 klijent - OAuth2RestTemplate - i a reddit.svojstva datoteka za sva svojstva povezana s autentifikacijom:
@Configuration @ EnableOAuth2Client @PropertySource ("classpath: reddit.properties") zaštićena statička klasa ResourceConfiguration {@Value ("$ {accessTokenUri}") private String accessTokenUri; @Value ("$ {userAuthorizationUri}") privatni niz userAuthorizationUri; @Value ("$ {clientID}") privatni niz clientID; @Value ("$ {clientSecret}") privatni niz clientSecret; @Bean public OAuth2ProtectedResourceDetails reddit () {AuthorizationCodeResourceDetails detalji = novi AuthorizationCodeResourceDetails (); detalji.setId ("reddit"); details.setClientId (clientID); details.setClientSecret (clientSecret); details.setAccessTokenUri (accessTokenUri); details.setUserAuthorizationUri (userAuthorizationUri); detalji.setTokenName ("oauth_token"); details.setScope (Arrays.asList ("identitet")); details.setPreEstablishedRedirectUri ("// localhost / login"); details.setUseCurrentUri (netačno); detalji povrata; } @Bean public OAuth2RestTemplate redditRestTemplate (OAuth2ClientContext clientContext) {OAuth2RestTemplate template = new OAuth2RestTemplate (reddit (), clientContext); AccessTokenProvider accessTokenProvider = novi AccessTokenProviderChain (nizovi. AsList (novi MyAuthorizationCodeAccessTokenProvider (), novi ImplicitAccessTokenProvider (), novi ResourceOwnerPasswordAccessTokenProviderCredenCroverCentral (ClientProvider) template.setAccessTokenProvider (accessTokenProvider); predložak za povratak; }}
I “reddit.svojstva“:
clientID = xxxxxxxx clientSecret = xxxxxxxx accessTokenUri = // www.reddit.com/api/v1/access_token userAuthorizationUri = // www.reddit.com/api/v1/authorize
Možete dobiti svoj vlastiti tajni kôd izradom aplikacije Reddit sa //www.reddit.com/prefs/apps/
Koristit ćemo OAuth2RestTemplate do:
- Nabavite pristupni token potreban za pristup udaljenom resursu.
- Pristupite udaljenom resursu nakon dobivanja pristupnog tokena.
Također imajte na umu kako smo dodali opseg “identitet”U Reddit OAuth2ProtectedResourceDetails kako bismo kasnije mogli doći do podataka o korisničkom računu.
4. Prilagođeno AuthorizationCodeAccessTokenProvider
Implementacija Reddit OAuth2 malo se razlikuje od standardne. I tako - umjesto da elegantno proširite AuthorizationCodeAccessTokenProvider - zapravo moramo nadjačati neke njegove dijelove.
Postoje github problemi s praćenjem poboljšanja zbog kojih to neće biti potrebno, ali ti problemi još nisu gotovi.
Jedna od nestandardnih stvari koje Reddit čini jest - kada preusmjerimo korisnika i zatražimo da se ovjeri pomoću Reddita, u URL-u za preusmjeravanje moramo imati neke prilagođene parametre. Točnije - ako tražimo token za trajni pristup od Reddita - moramo dodati parametar “trajanje"S vrijednošću"trajni“.
Dakle, nakon produženja AuthorizationCodeAccessTokenProvider - dodali smo ovaj parametar u getRedirectForAuthorization () metoda:
requestParameters.put ("trajanje", "trajno");
Potpuni izvorni kod možete provjeriti ovdje.
5. The Inicijalizator poslužitelja
Dalje - stvorimo svoj običaj Inicijalizator poslužitelja.
Moramo dodati zrno filtra s id-om oauth2ClientContextFilter, tako da ga možemo koristiti za pohranu trenutnog konteksta:
javna klasa ServletInitializer proširuje AbstractDispatcherServletInitializer {@Override protected WebApplicationContext createServletApplicationContext () {AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext (); context.register (WebConfig.class, SecurityConfig.class); povratni kontekst; } @Override protected String [] getServletMappings () {return new String [] {"/"}; } @Override zaštićen WebApplicationContext createRootApplicationContext () {return null; } @Override public void onStartup (ServletContext servletContext) baca ServletException {super.onStartup (servletContext); registerProxyFilter (servletContext, "oauth2ClientContextFilter"); registerProxyFilter (servletContext, "springSecurityFilterChain"); } privatna praznina registerProxyFilter (ServletContext servletContext, naziv niza) {DelegatingFilterProxy filter = novi DelegatingFilterProxy (ime); filter.setContextAttribute ("org.springframework.web.servlet.FrameworkServlet.CONTEXT.dispatcher"); servletContext.addFilter (ime, filtar) .addMappingForUrlPatterns (null, false, "/ *"); }}
6. MVC konfiguracija
Sada - pogledajmo našu MVC konfiguraciju naše jednostavne web-aplikacije:
@Configuration @EnableWebMvc @ComponentScan (basePackages = {"org.baeldung.web"}) javna klasa WebConfig implementira WebMvcConfigurer {@Bean public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer) (returnPressholderConfigurer) { } @Bean public ViewResolver viewResolver () {InternalResourceViewResolver viewResolver = novi InternalResourceViewResolver (); viewResolver.setPrefix ("/ WEB-INF / jsp /"); viewResolver.setSuffix (". jsp"); povratak viewResolver; } @Override public void configureDefaultServletHandling (DefaultServletHandlerConfigurer configurer) {configurer.enable (); } javna void addResourceHandlers (registar ResourceHandlerRegistry) {registry.addResourceHandler ("/ resources / **"). addResourceLocations ("/ resources /"); } @Override public void addViewControllers (registar ViewControllerRegistry) {registry.addViewController ("/ home.html"); }}
7. Sigurnosna konfiguracija
Dalje - pogledajmo glavna konfiguracija Spring Security:
@Configuration @EnableWebSecurity javna klasa SecurityConfig proširuje WebSecurityConfigurerAdapter {@Override zaštićena void konfiguracija (AuthenticationManagerBuilder auth) baca iznimku {auth.inMemoryAuthentication (); } @Override zaštićena void konfiguracija (HttpSecurity http) baca Iznimku {http .anonymous (). Disable () .csrf (). Disable () .authorizeRequests () .antMatchers ("/ home.html"). HasRole ("USER" ) .and () .httpBasic () .authenticationEntryPoint (oauth2AuthenticationEntryPoint ()); } private LoginUrlAuthenticationEntryPoint oauth2AuthenticationEntryPoint () {return new LoginUrlAuthenticationEntryPoint ("/ login"); }}
Napomena: Dodali smo jednostavnu sigurnosnu konfiguraciju koja preusmjerava na “/prijaviti se”Koji dobivaju korisničke podatke i učitavaju provjeru autentičnosti iz njih - kako je objašnjeno u sljedećem odjeljku.
8. RedditController
Sada - pogledajmo naš kontroler RedditController.
Koristimo metodu redditLogin () za dobivanje korisničkih podataka s njegovog Reddit računa i učitavanje provjere autentičnosti s njega - kao u sljedećem primjeru:
@Controller javna klasa RedditController {@Autowired private OAuth2RestTemplate redditRestTemplate; @RequestMapping ("/ login") javni niz redditLogin () {JsonNode node = redditRestTemplate.getForObject ("//oauth.reddit.com/api/v1/me", JsonNode.class); UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken (node.get ("name"). AsText (), redditRestTemplate.getAccessToken (). GetValue (), Arrays.asList (new SimpleGrantedAuthority ("ROLE_USER"; SecurityContextHolder.getContext (). SetAuthentication (auth); return "preusmjeravanje: home.html"; }}
Zanimljiv detalj ove varljivo jednostavne metode - predložak reddit provjerava je li pristupni token dostupan prije izvršavanja bilo kojeg zahtjeva; stječe žeton ako nije dostupan.
Dalje - informacije predstavljamo našem vrlo pojednostavljenom prednjem dijelu.
9. home.jsp
Napokon - pogledajmo home.jsp - za prikaz podataka preuzetih iz korisnikovog Reddit računa:
10. Zaključak
U ovom uvodnom članku istražili smo autentičnost pomoću Reddit OAuth2 API-ja i prikazivanje nekih vrlo osnovnih podataka u jednostavnom prednjem dijelu.
Sad kad smo provjerili autentičnost, istražit ćemo još zanimljivih stvari s Reddit API-jem u sljedećem članku ove nove serije.
The puna provedba ovog vodiča možete pronaći u projektu github - ovo je projekt zasnovan na Eclipseu, pa bi ga trebalo lako uvesti i pokrenuti kakav jest.