# 引
根据不同场景,不一定要直接访问认证服务器(单点压力,步骤繁琐)
实现在客户端输入用户名和密码就等登陆系统.
# 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;
}
注意两个问题:
- 使用Base64加密client_id和client_secret
- 返回值必须要有实体类.
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;
}
# 封装
- EnableOAuth2Client
@EnableOAuth2Client
@SpringBootApplication(exclude = {SecurityAutoConfiguration.class})
public class KpiApplication {
public static void main(String[] args) {
SpringApplication.run(KpiApplication.class, args);
}
}
- 使用 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)
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_id和client_secret