Godkendelse med Reddit OAuth2 og Spring Security

1. Oversigt

I denne vejledning bruger vi Spring Security OAuth til at godkende med Reddit API.

2. Maven-konfiguration

For det første for at kunne bruge Spring Security OAuth - skal vi tilføje følgende afhængighed af vores pom.xml (selvfølgelig langs enhver anden forårsafhængighed, du måtte bruge):

 org.springframework.security.oauth spring-security-oauth2 2.0.6.RELEASE 

3. Konfigurer OAuth2-klient

Næste - lad os konfigurere vores OAuth2-klient - OAuth2RestTemplate - og en reddit.properties fil til alle godkendelsesrelaterede egenskaber:

@Configuration @ EnableOAuth2Client @PropertySource ("classpath: reddit.properties") beskyttet statisk klasse ResourceConfiguration {@Value ("$ {accessTokenUri}") privat String accessTokenUri; @Value ("$ {userAuthorizationUri}") privat streng userAuthorizationUri; @Value ("$ {clientID}") privat streng-clientID; @Value ("$ {clientSecret}") privat streng clientSecret; @Bean public OAuth2ProtectedResourceDetails reddit () {AuthorizationCodeResourceDetails details = new AuthorizationCodeResourceDetails (); details.setId ("reddit"); details.setClientId (clientID); details.setClientSecret (clientSecret); details.setAccessTokenUri (accessTokenUri); details.setUserAuthorizationUri (userAuthorizationUri); details.setTokenName ("oauth_token"); details.setScope (Arrays.asList ("identitet")); details.setPreEstablishedRedirectUri ("// localhost / login"); details.setUseCurrentUri (false); returnere detaljer; } @Bean public OAuth2RestTemplate redditRestTemplate (OAuth2ClientContext clientContext) {OAuth2RestTemplate template = new OAuth2RestTemplate (reddit (), clientContext); AccessTokenProvider accessTokenProvider = ny AccessTokenProviderChain (Arrays. AsList (ny MyAuthorizationCodeAccessTokenProvider (), ny ImplicitAccessTokenProvider (), ny ResourceOwnerPasswordAccessTokenProvider (), ny ClientCredentialsAccessTokenProvider; template.setAccessTokenProvider (accessTokenProvider); returskabelon; }}

Og “reddit.properties“:

clientID = xxxxxxxx clientSecret = xxxxxxxx accessTokenUri = // www.reddit.com/api/v1/access_token userAuthorizationUri = // www.reddit.com/api/v1/authorize

Du kan få din egen hemmelige kode ved at oprette en Reddit-app fra //www.reddit.com/prefs/apps/

Vi skal bruge OAuth2RestTemplate til:

  1. Hent det adgangstoken, der er nødvendigt for at få adgang til fjernressourcen.
  2. Få adgang til den eksterne ressource efter at have fået adgangstokenet.

Bemærk også, hvordan vi tilføjede omfanget “identitet”Til Reddit OAuth2ProtectedResourceDetails så vi kan hente brugernes kontooplysninger senere.

4. Brugerdefineret AuthorizationCodeAccessTokenProvider

Reddit OAuth2-implementeringen er lidt anderledes end standarden. Og så - i stedet for elegant at udvide AuthorizationCodeAccessTokenProvider - vi skal faktisk tilsidesætte nogle dele af det.

Der er github-problemer, der sporer forbedringer, der gør dette ikke nødvendigt, men disse problemer er endnu ikke udført.

En af de ikke-standardiserede ting, som Reddit gør, er - når vi omdirigerer brugeren og beder ham om at godkende med Reddit, skal vi have nogle brugerdefinerede parametre i omdirigerings-URL'en. Mere specifikt - hvis vi beder om et permanent adgangstoken fra Reddit - skal vi tilføje en parameter “varighed”Med værdien“permanent“.

Så efter udvidelse AuthorizationCodeAccessTokenProvider - vi har tilføjet denne parameter i getRedirectForAuthorization () metode:

 requestParameters.put ("varighed", "permanent");

Du kan kontrollere den fulde kildekode herfra.

5. Den ServerInitializer

Næste - lad os oprette vores brugerdefinerede ServerInitializer.

Vi skal tilføje en filterbønne med id oauth2ClientContextFilter, så vi kan bruge den til at gemme den aktuelle kontekst:

offentlig klasse ServletInitializer udvider AbstractDispatcherServletInitializer {@Override beskyttet WebApplicationContext createServletApplicationContext () {AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext (); context.register (WebConfig.class, SecurityConfig.class); returnere kontekst; } @ Override-beskyttet streng [] getServletMappings () {returner ny streng [] {"/"}; } @ Override beskyttet WebApplicationContext createRootApplicationContext () {return null; } @ Override offentlig ugyldighed onStartup (ServletContext servletContext) kaster ServletException {super.onStartup (servletContext); registerProxyFilter (servletContext, "oauth2ClientContextFilter"); registerProxyFilter (servletContext, "springSecurityFilterChain"); } privat ugyldigt registerProxyFilter (ServletContext servletContext, String name) {DelegatingFilterProxy filter = new DelegatingFilterProxy (name); filter.setContextAttribute ("org.springframework.web.servlet.FrameworkServlet.CONTEXT.dispatcher"); servletContext.addFilter (navn, filter) .addMappingForUrlPatterns (null, false, "/ *"); }}

6. MVC-konfiguration

Lad os nu se på vores MVC-konfiguration af vores enkle webapp:

@Configuration @EnableWebMvc @ComponentScan (basePackages = {"org.baeldung.web"}) public class WebConfig implementerer WebMvcConfigurer {@Bean public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer () {returner ny PropertySourcesPlaceholderConfigurer; } @Bean public ViewResolver viewResolver () {InternalResourceViewResolver viewResolver = ny InternalResourceViewResolver (); viewResolver.setPrefix ("/ WEB-INF / jsp /"); viewResolver.setSuffix (". jsp"); returner visningResolver; } @ Override public void configureDefaultServletHandling (DefaultServletHandlerConfigurer configurer) {configurer.enable (); } public void addResourceHandlers (ResourceHandlerRegistry registry) {registry.addResourceHandler ("/ resources / **"). addResourceLocations ("/ resources /"); } @ Override offentlig ugyldighed addViewControllers (ViewControllerRegistry registry) {registry.addViewController ("/ home.html"); }}

7. Sikkerhedskonfiguration

Næste - lad os se på den primære Spring Security-konfiguration:

@Configuration @EnableWebSecurity offentlig klasse SecurityConfig udvider WebSecurityConfigurerAdapter {@Override beskyttet ugyldig konfiguration (AuthenticationManagerBuilder auth) kaster Undtagelse {auth.inMemoryAuthentication (); } @ Override beskyttet ugyldig konfiguration (HttpSecurity http) kaster undtagelse {http. Anonym (). Deaktiver () .csrf (). Deaktiver (). Autorisationsanmodninger () .antMatchers ("/ home.html"). HasRole ("USER" ) .og () .httpBasic () .authenticationEntryPoint (oauth2AuthenticationEntryPoint ()); } privat LoginUrlAuthenticationEntryPoint oauth2AuthenticationEntryPoint () {returner nyt LoginUrlAuthenticationEntryPoint ("/ login"); }}

Bemærk: Vi tilføjede en simpel sikkerhedskonfiguration, der omdirigerer til “/Log på”Som får brugeroplysningerne og indlæser godkendelse fra dem - som forklaret i det følgende afsnit.

8. RedditController

Lad os nu se på vores controller RedditController.

Vi bruger metoden redditLogin () for at hente brugeroplysningerne fra sin Reddit-konto og indlæse en godkendelse derfra - som i følgende eksempel:

@Controller offentlig klasse RedditController {@Autowired privat OAuth2RestTemplate redditRestTemplate; @RequestMapping ("/ login") offentlig String 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); returner "redirect: home.html"; }}

En interessant detalje af denne vildledende enkle metode - reddit-skabelonen kontrollerer, om adgangstokenet er tilgængeligt, før en anmodning udføres; det erhverver et token, hvis et ikke er tilgængeligt.

Dernæst præsenterer vi oplysningerne for vores meget forenklede frontend.

9. hjem.jsp

Endelig - lad os se på hjem.jsp - for at få vist den information, der er hentet fra brugerens Reddit-konto:

10. Konklusion

I denne indledende artikel udforskede vi godkendelse med Reddit OAuth2 API og vise nogle meget grundlæggende oplysninger i en simpel frontend.

Nu hvor vi er godkendt, skal vi udforske at gøre mere interessante ting med Reddit API i den næste artikel i denne nye serie.

Det fuld implementering af denne vejledning kan findes i github-projektet - dette er et Eclipse-baseret projekt, så det skal være let at importere og køre som det er.


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