Rest API: 基本认证和摘要认证

    xiaoxiao2021-03-25  132

    用spring security实现Rest API的基本认证(Basic)和摘要认证(Digest):

    Basic 认证

    1. server - spring security配置

    package com.pechen.config; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; @Configuration @EnableWebSecurity public class WebSecurityConfig extends WebSecurityConfigurerAdapter { public final static String REALM="MY_REALM"; @Autowired public void configureGlobalSecurity(AuthenticationManagerBuilder auth) throws Exception { auth.inMemoryAuthentication().withUser("admin").password("admin").roles("ADMIN") .and().withUser("test").password("test").roles("USER"); } @Override protected void configure(HttpSecurity http) throws Exception { http.csrf().disable() .authorizeRequests() .anyRequest().authenticated() .and().httpBasic().realmName(REALM).authenticationEntryPoint(getBasicAuthEntryPoint()); // .and().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);//We don't need sessions to be created. } @Bean public CustomBasicAuthenticationEntryPoint getBasicAuthEntryPoint(){ return new CustomBasicAuthenticationEntryPoint(); } @Bean public AuthenticationManager authenticationManagerBean() throws Exception { // altough this seems like useless code, // its required to prevend spring boot auto-configuration return super.authenticationManagerBean(); } } package com.pechen.config; import java.io.IOException; import java.io.PrintWriter; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.security.core.AuthenticationException; import org.springframework.security.web.authentication.www.BasicAuthenticationEntryPoint; public class CustomBasicAuthenticationEntryPoint extends BasicAuthenticationEntryPoint { @Override public void commence(final HttpServletRequest request, final HttpServletResponse response, final AuthenticationException authException) throws IOException, ServletException { response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); response.addHeader("WWW-Authenticate", "Basic realm=\"" + getRealmName() + "\""); PrintWriter writer = response.getWriter(); writer.println("HTTP Status 401 : " + authException.getMessage()); } @Override public void afterPropertiesSet() throws Exception { setRealmName(WebSecurityConfig.REALM); super.afterPropertiesSet(); } }

    2. server - rest api

    package com.pechen.rest; import java.util.Map; import org.springframework.web.bind.annotation.RequestHeader; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RestController; /** * Authentication service. */ @RestController @RequestMapping(path = "/") public class RestService { @RequestMapping(path = "/login", method = RequestMethod.GET) public String login(@RequestHeader Map<String, Object> headers){ return "Login success..."; } }

    3. client - rest template(加上Authorization的头部即可)

    package com.pechen.test; import java.util.Base64; import org.junit.Test; import org.springframework.http.HttpEntity; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; import org.springframework.http.ResponseEntity; import org.springframework.web.client.RestTemplate; public class AuthServiceTest { private HttpHeaders getHeaders(){ String plainCredentials="admin:admin"; String base64Credentials = Base64.getEncoder().encodeToString(plainCredentials.getBytes()); HttpHeaders headers = new HttpHeaders(); headers.add("Authorization", "Basic " + base64Credentials); return headers; } @Test public void testLogin() { RestTemplate restTemplate = new RestTemplate(); HttpEntity<String> request = new HttpEntity<String>(getHeaders()); ResponseEntity<String> response = restTemplate.exchange("http://localhost:8080/login", HttpMethod.GET, request, String.class); System.out.println(response.getBody()); } }

    Digest 认证

    1. server - spring security配置

    package com.pechen.config; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.config.http.SessionCreationPolicy; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.web.authentication.www.DigestAuthenticationFilter; @Configuration @EnableWebSecurity public class WebSecurityConfig extends WebSecurityConfigurerAdapter { public final static String REALM="MY_REALM"; @Autowired public void configureGlobalSecurity(AuthenticationManagerBuilder auth) throws Exception { auth.inMemoryAuthentication().withUser("admin").password("admin").roles("ADMIN") .and().withUser("test").password("test").roles("USER"); } @Override protected void configure(HttpSecurity http) throws Exception { http.csrf().disable() .authorizeRequests() .anyRequest().authenticated() .and().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS) .and().exceptionHandling().authenticationEntryPoint(getDigestEntryPoint()) .and().addFilter(getDigestAuthenticationFilter(getDigestEntryPoint())); } @Bean public MyDigestAuthenticationEntryPoint getDigestEntryPoint() { MyDigestAuthenticationEntryPoint digestAuthenticationEntryPoint = new MyDigestAuthenticationEntryPoint(); digestAuthenticationEntryPoint.setKey("mykey"); digestAuthenticationEntryPoint.setNonceValiditySeconds(120); digestAuthenticationEntryPoint.setRealmName(REALM); return digestAuthenticationEntryPoint; } public DigestAuthenticationFilter getDigestAuthenticationFilter( MyDigestAuthenticationEntryPoint digestAuthenticationEntryPoint) throws Exception { DigestAuthenticationFilter digestAuthenticationFilter = new DigestAuthenticationFilter(); digestAuthenticationFilter.setAuthenticationEntryPoint(digestAuthenticationEntryPoint); digestAuthenticationFilter.setUserDetailsService(userDetailsServiceBean()); return digestAuthenticationFilter; } @Override @Bean public UserDetailsService userDetailsServiceBean() throws Exception { return super.userDetailsServiceBean(); } } package com.pechen.config; import org.springframework.security.web.authentication.www.DigestAuthenticationEntryPoint; public class MyDigestAuthenticationEntryPoint extends DigestAuthenticationEntryPoint { @Override public void afterPropertiesSet() throws Exception{ super.afterPropertiesSet(); setRealmName(WebSecurityConfig.REALM); } } 2. server - rest api 同上 3. client - 配置rest template使用Digest认证

    package com.pechen.rest; import org.apache.http.auth.AuthScope; import org.apache.http.auth.UsernamePasswordCredentials; import org.apache.http.client.CredentialsProvider; import org.apache.http.impl.client.BasicCredentialsProvider; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClientBuilder; import org.springframework.http.client.HttpComponentsClientHttpRequestFactory; import org.springframework.web.client.RestTemplate; public class RestTempleteConfig { public RestTemplate getRestTemplate() { CloseableHttpClient client = HttpClientBuilder.create().setDefaultCredentialsProvider(provider()) .useSystemProperties().build(); HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactoryDigestAuth( client); return new RestTemplate(requestFactory); } private CredentialsProvider provider() { CredentialsProvider provider = new BasicCredentialsProvider(); UsernamePasswordCredentials credentials = new UsernamePasswordCredentials("admin", "admin"); provider.setCredentials(AuthScope.ANY, credentials); return provider; } } package com.pechen.rest; import java.net.URI; import org.apache.http.HttpHost; import org.apache.http.client.AuthCache; import org.apache.http.client.HttpClient; import org.apache.http.client.protocol.ClientContext; import org.apache.http.impl.auth.DigestScheme; import org.apache.http.impl.client.BasicAuthCache; import org.apache.http.protocol.BasicHttpContext; import org.apache.http.protocol.HttpContext; import org.springframework.http.HttpMethod; import org.springframework.http.client.HttpComponentsClientHttpRequestFactory; public class HttpComponentsClientHttpRequestFactoryDigestAuth extends HttpComponentsClientHttpRequestFactory { public HttpComponentsClientHttpRequestFactoryDigestAuth(HttpClient client) { super(client); } @Override protected HttpContext createHttpContext(HttpMethod httpMethod, URI uri) { return createHttpContext(uri); } private HttpContext createHttpContext(URI uri) { // Create AuthCache instance AuthCache authCache = new BasicAuthCache(); // Generate DIGEST scheme object, initialize it and add it to the local auth cache DigestScheme digestAuth = new DigestScheme(); // If we already know the realm name digestAuth.overrideParamter("realm", "myrealm"); HttpHost targetHost = new HttpHost(uri.getHost(), uri.getPort()); authCache.put(targetHost, digestAuth); // Add AuthCache to the execution context BasicHttpContext localcontext = new BasicHttpContext(); localcontext.setAttribute(ClientContext.AUTH_CACHE, authCache); return localcontext; } } 4. 使用rest template发送请求

    package com.pechen.test; import org.junit.Test; import org.springframework.http.HttpMethod; import org.springframework.http.ResponseEntity; import org.springframework.web.client.RestTemplate; import jdk.nashorn.internal.ir.annotations.Ignore; public class RestClient { @Test public void whenSecuredRestApiIsConsumed_then200OK() { RestTemplate restTemplate = new RestTempleteConfig().getRestTemplate(); String uri = "http://localhost:8080/login"; ResponseEntity<String> entity = restTemplate.exchange(uri, HttpMethod.GET, null, String.class); System.out.println(entity.getStatusCode()); System.out.println(entity.getBody()); } }

    
    转载请注明原文地址: https://ju.6miu.com/read-5830.html

    最新回复(0)