#

根据不同场景,不一定要直接访问认证服务器(单点压力,步骤繁琐)

实现在客户端输入用户名和密码就等登陆系统.

# feign

使用 feign 请求/oauth/token获取access_token,使用basic认证的方式.(其他客户端也是如此)

参考源码javadoc:

org.springframework.security.oauth2.provider.endpoint.TokenEndpoint

# 生命feign的API

@FeignClient(value = "business-oauth2")
public interface LoginFeign {

    @PostMapping(value = "/oauth/token")
    ResponseEntity<String> login(@RequestHeader(value = "Authorization")String authorization,
                         @RequestParam("grant_type")String grantType,
                         @RequestParam("username")String username,
                         @RequestParam("password")String password
    );
}

# EnableFeignClients

@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
public class BusinessProfileApplication {

    public static void main(String[] args) {
        SpringApplication.run(BusinessProfileApplication.class, args);
    }

}

# 在controller中使用

@PostMapping(value = "/login")
public ResponseEntity<String> login(@RequestBody LoginParams loginParams) {

    String username = loginParams.getUsername();
    String password = loginParams.getPassword();

    log.info("username={},password={}", username, password);

    ResponseEntity<String> entity =
      loginFeign.login(
          "Basic Y2xpZW50OnNlY3JldA==",
          this.oauth2GrantType,
          username,
          password);
    // entity.getBody()
    log.info(entity.getBody());
    return entity;
}

注意两个问题:

  1. 使用Base64加密client_id和client_secret
  2. 返回值必须要有实体类.ResponseEntity<String>

# OAuth2RestTemplate

在依賴中增加 org.springframework.security.oauth:spring-security-oauth2

# 测试

public void testOAuth() {
    AccessTokenRequest atr = new DefaultAccessTokenRequest();
    OAuth2RestTemplate oAuth2RestTemplate = new OAuth2RestTemplate(resource(), new DefaultOAuth2ClientContext(atr));
    try {
        System.out.println(oAuth2RestTemplate.getAccessToken());
        System.out.println(oAuth2RestTemplate.getAccessToken().getRefreshToken());
    } catch (OAuth2AccessDeniedException e) {
        System.out.println("登入失敗" + e.getHttpErrorCode()); // 403
        System.out.println("登入失敗" + e.getOAuth2ErrorCode()); // access_denied
        System.out.println("登入失敗" + e.getMessage()); //Access token denied.
        System.out.println("登入失敗" + e.getLocalizedMessage()); // Access token denied.
        System.out.println("登入失敗" + e.getSummary()); // error="access_denied", error_description="Access token denied."
    }
}

protected OAuth2ProtectedResourceDetails resource() {
    ResourceOwnerPasswordResourceDetails resource = new ResourceOwnerPasswordResourceDetails();
    List scopes = new ArrayList<String>(2);
    scopes.add("account");
    scopes.add("role");
    resource.setAccessTokenUri("http://localhost:8081/oauth/token");
    resource.setClientId("clientkpi");
    resource.setClientSecret("123456");
    resource.setGrantType("password");
    resource.setScope(scopes);
    resource.setUsername("sam.chu=");
    resource.setPassword("12345678");
    return resource;
}

# 封装

  1. EnableOAuth2Client
@EnableOAuth2Client
@SpringBootApplication(exclude = {SecurityAutoConfiguration.class})
public class KpiApplication {

    public static void main(String[] args) {
        SpringApplication.run(KpiApplication.class, args);
    }
}
  1. 使用 RestTemplate 发送post(新增)和get(获取)

get

public void restGet() throws IOException {
    String url = "http://localhost:8082/api/v1/role";
    RestTemplate restTemplate = new RestTemplate();
    HttpHeaders headers = new HttpHeaders();
    headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON_UTF8));
    headers.add("Authorization", String.format("%s %s", "bearer", "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOlsia3BpIiwiYWNjb3VudCJdLCJ1c2VyX25hbWUiOiJzYW0uY2h1PSIsInNjb3BlIjpbImFjY291bnQiLCJyb2xlIl0sImV4cCI6MTQ4NzU3NDUzNywiYXV0aG9yaXRpZXMiOlsiUk9MRV9VU0VSIl0sImp0aSI6ImNiMzc0OGFmLTc2NGUtNDNiNy1iNTVjLTU4ZjQzZWQwOTU0MCIsImNsaWVudF9pZCI6ImNsaWVudGtwaSJ9.9Wwk5-GrJ_xdVOcOexoDhIXEznHqm3ssBfob0FeSFgA"));
    HttpEntity<String> entity = new HttpEntity<String>(headers);
    ResponseEntity<String> response = restTemplate.exchange(url, HttpMethod.GET, entity, String.class);
    if (response.getStatusCode().equals(HttpStatus.OK)) {
        System.out.println(response.getBody());
    }
}

post

public void restPost() throws IOException {
    String url = "http://localhost:8082/api/v1/role";
    RestTemplate restTemplate = new RestTemplate();
    HttpHeaders headers = new HttpHeaders();
    headers.setContentType(MediaType.APPLICATION_JSON_UTF8);
    headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON_UTF8));
    headers.add("Authorization", String.format("%s %s", "bearer", "eyJhbGciOiJIUzI1.NiIsInR5cCI6I.kpXVCJ9"));
    RoleDto roleDto = new RoleDto();
    roleDto.setCode("ROLE_GINTAMA");
    roleDto.setLabel("xxx");
    HttpEntity<RoleDto> entity = new HttpEntity<RoleDto>(roleDto, headers);
    ResponseEntity<String> response = restTemplate.exchange(url, HttpMethod.POST, entity, String.class, new HashMap<String, String>());
    if (response.getStatusCode().equals(HttpStatus.CREATED)) {
        System.out.println(response.getBody());
    }
}

# 使用loadBalanced

@LoadBalanced
@Bean
public OAuth2RestTemplate restTemplate(UserInfoRestTemplateFactory factory) {
    return factory.getUserInfoRestTemplate();
}

# 参考

https://www.cnblogs.com/softidea/p/7045809.html (opens new window)

http://samchu.logdown.com/posts/1437422-oathe2-login-use-okhttpclient-and-oauth2resttemplate?utm_source=tuicool&utm_medium=referral (opens new window)

use JWT OAuth2 and spring-security Create AuthorizationServer (opens new window)

http://samchu.logdown.com/posts/1433379 (opens new window)

http://www.tuicool.com/articles/eeQvy2j (opens new window)

# RestTemplate

# okHttp3

# 总结

使用 restTemplate,oauth2RestTemplate,feign 都是使用Basic认证的方式.feign要手动Base64加密client_idclient_secret