在我们使用oauth2的时候我出现的一个问题就是如下截图,如果有问题可以咨询我的v。
G654377984
在接下来我会通过代码来介绍和说明我出现的问题,这个oauth2的学习过程十分的痛苦只有我们了解完代码我们才能更好的了解我们代码出现的问题,我就是因为刚开始不清楚代码的原理,才导致的我们问题的出现和迟迟的不能解决,这个问题困惑了很久。不啰嗦,下面开始讲解和说明、
密码模式
首先我们看上面的请求路径,首先我们要去认证服务器去认证我们客户端id、返回值类型:
是code,作用范围:我在数据库中定义的是all,我们的跳转路径,数据库我随便定义的一个。
我们看返回的
我们返回的时候我们携带了我们的code
此时我们通过postman去测试请求token
当我们点击测试的时候,这时候问题出现了,就如文章刚开始时的问题。
此时我们就要进行开始测试找出问题的所在
我们接下来会一部分一部分的说 首先我们实现了了UserDetailsService 这个类重写了方法。
/*****
* 自定义授权认证类
*/
@Service
public class UserDetailsServiceImpl implements UserDetailsService {
@Autowired
ClientDetailsService clientDetailsService;
@Autowired
UserFeign userFeign;
/****
* 自定义授权认证
* @param username
* @return
* @throws UsernameNotFoundException
*/
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
//取出身份,如果身份为空说明没有认证
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
//没有认证统一采用httpbasic认证,httpbasic中存储了client_id和client_secret,开始认证client_id和client_secret
if(authentication==null){
ClientDetails clientDetails = clientDetailsService.loadClientByClientId(username);
if(clientDetails!=null){
//秘钥
String clientSecret = clientDetails.getClientSecret();
//静态方式
//return new User(username,new BCryptPasswordEncoder().encode(clientSecret), AuthorityUtils.commaSeparatedStringToAuthorityList(""));
//数据库查找方式
return new User(username,clientSecret, AuthorityUtils.commaSeparatedStringToAuthorityList(""));
}
}
if (StringUtils.isEmpty(username)) {
return null;
}
// ********************************用户名和密码登录开始*****************************************
if (StringUtils.isEmpty(username)) {
System.out.println("----------------2222----------------------------");
return null;
}
System.out.println("username:"+username);
Result<com.offcn.user.dao.User> user = userFeign.findByUserName(username);//执行查询数据库
System.out.println("username:"+user.getData().getUsername());
System.out.println("passsword:"+user.getData().getPassword());
String permissions="salesman,accountant,user";
System.out.println("permissions:"+permissions);
UserJwt userDetails = new UserJwt(username,user.getData().getPassword(), AuthorityUtils.commaSeparatedStringToAuthorityList(permissions));
//=======================用户账号和密码认证结束==========================
return userDetails;
/*//根据用户名查询用户信息
String pwd = new BCryptPasswordEncoder().encode("dongyimai");
//创建User对象
String permissions = "goods_list,seckill_list";
UserJwt userDetails = new UserJwt(username,pwd,AuthorityUtils.commaSeparatedStringToAuthorityList(permissions));
return userDetails;*/
}
}
我们通过密码模式进行认证后,我们点击确定认证后,会发送给我们授权码,然后我们拿着授权码去请求token,如图上面的postman的测试。接下来我们进行打断点测试
我们打断点发现我们的Authentication还没有被认证,我们去调用ClientDetails clientDetails = clientDetailsService.loadClientByClientId(username);
注意:我们这里调用的方法是通过底层自动去帮我们查询的数据库去判断我们的客户端id和secret等信息,看下图
此时我们继续往下断点此时我们发现我们已经认证成功了(注意我们现在是拿到了授权码,现在是通过postman去拿token),继续讲,看上面的完整代码我们if这里是false我们是已经认证过了,所以if这里跳过了,我们看下面第二章截图,然后这里我们通过远程feign调用的是用户微服务的查询客户端的信息,此时我们查询的数据库是用户为服务的数据库,这里我们的用户名和密码是我们上面截图的basc auth输入的用户名和密码进行判断的,我出现的问题也是在这里,我认为的是bisc认证输入的账号和密码是对比的是client_detal数据库中的账号密码所以我输入的账号密码也是这个数据中的账号密码,但是我们的tb_user 中并不存在,所以就出现了文章开头的问题。继续讲,我们最终拿到了用户的信息我们封装到了UserJWT中,这个封装实体类继承了UserDetail所以我们放回。继续看下面。
我们上面介绍了我们将查询到的结果封装到了UserJWT中,实际上是UserDetail类型的,接下来我们看看是谁调用了这个方法?看下面代码。UserDetails userDetails = userDetailsService.loadUserByUsername(name);我们这里调用了这个方法。并且看代码我们将查询到的存入到response中,其他的都交由oauth2去处理。更多底层的代码我们要去看更多的底层原理,篇幅有限不再赘述。
@Component
public class CustomUserAuthenticationConverter extends DefaultUserAuthenticationConverter {
@Autowired
UserDetailsService userDetailsService;
@Override
public Map<String, ?> convertUserAuthentication(Authentication authentication) {
LinkedHashMap response = new LinkedHashMap();
String name = authentication.getName();
response.put("username", name);
Object principal = authentication.getPrincipal();
UserJwt userJwt = null;
if(principal instanceof UserJwt){
userJwt = (UserJwt) principal;
}else{
//refresh_token默认不去调用userdetailService获取用户信息,这里我们手动去调用,得到 UserJwt
UserDetails userDetails = userDetailsService.loadUserByUsername(name);
userJwt = (UserJwt) userDetails;
}
response.put("name", userJwt.getName());
response.put("id", userJwt.getId());
if (authentication.getAuthorities() != null && !authentication.getAuthorities().isEmpty()) {
response.put("authorities", AuthorityUtils.authorityListToSet(authentication.getAuthorities()));
}
return response;
}
}
下面贴出完整的代码也包括密码模式和授权模式
package com.dongyimai.oauth.s.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.bootstrap.encrypt.KeyProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.ClientDetailsService;
import org.springframework.security.oauth2.provider.client.JdbcClientDetailsService;
import org.springframework.security.oauth2.provider.token.DefaultAccessTokenConverter;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
import org.springframework.security.oauth2.provider.token.store.JwtTokenStore;
import org.springframework.security.oauth2.provider.token.store.KeyStoreKeyFactory;
import javax.annotation.Resource;
import javax.sql.DataSource;
import java.security.KeyPair;
@Configuration
@EnableAuthorizationServer
class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
//数据源,用于从数据库获取数据进行认证操作,测试可以从内存中获取
@Autowired
private DataSource dataSource;
//jwt令牌转换器
@Autowired
private JwtAccessTokenConverter jwtAccessTokenConverter;
//SpringSecurity 用户自定义授权认证类
@Autowired
UserDetailsService userDetailsService;
//授权认证管理器
@Autowired
AuthenticationManager authenticationManager;
//令牌持久化存储接口
@Autowired
TokenStore tokenStore;
@Autowired
private CustomUserAuthenticationConverter customUserAuthenticationConverter;
/***
* 客户端信息配置
* @param clients
* @throws Exception
*/
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.jdbc(dataSource).clients(clientDetails());
}
/***
* 授权服务器端点配置
* @param endpoints
* @throws Exception
*/
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints.accessTokenConverter(jwtAccessTokenConverter)
.authenticationManager(authenticationManager)//认证管理器
.tokenStore(tokenStore) //令牌存储
.userDetailsService(userDetailsService); //用户信息service
}
/***
* 授权服务器的安全配置
* @param oauthServer
* @throws Exception
*/
@Override
public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception {
oauthServer.allowFormAuthenticationForClients()
.passwordEncoder(new BCryptPasswordEncoder())
.tokenKeyAccess("permitAll()")
.checkTokenAccess("isAuthenticated()");
}
//读取密钥的配置
@Bean("keyProp")
public KeyProperties keyProperties(){
return new KeyProperties();
}
@Resource(name = "keyProp")
private KeyProperties keyProperties;
//客户端配置
@Bean
public ClientDetailsService clientDetails() {
return new JdbcClientDetailsService(dataSource);
}
@Bean
@Autowired
public TokenStore tokenStore(JwtAccessTokenConverter jwtAccessTokenConverter) {
return new JwtTokenStore(jwtAccessTokenConverter);
}
/****
* JWT令牌转换器
* @param customUserAuthenticationConverter
* @return
*/
@Bean
public JwtAccessTokenConverter jwtAccessTokenConverter(CustomUserAuthenticationConverter customUserAuthenticationConverter) {
JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
KeyPair keyPair = new KeyStoreKeyFactory(
keyProperties.getKeyStore().getLocation(), //证书路径 dongyimai.jks
keyProperties.getKeyStore().getSecret().toCharArray()) //证书秘钥 dongyimaiapp
.getKeyPair(
keyProperties.getKeyStore().getAlias(), //证书别名 dongyimai
keyProperties.getKeyStore().getPassword().toCharArray()); //证书密码 dongyimai
converter.setKeyPair(keyPair);
//配置自定义的CustomUserAuthenticationConverter
DefaultAccessTokenConverter accessTokenConverter = (DefaultAccessTokenConverter) converter.getAccessTokenConverter();
accessTokenConverter.setUserTokenConverter(customUserAuthenticationConverter);
return converter;
}
}
package com.dongyimai.oauth.s.config;
import com.dongyimai.oauth.s.util.UserJwt;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.oauth2.provider.token.DefaultUserAuthenticationConverter;
import org.springframework.stereotype.Component;
import java.util.LinkedHashMap;
import java.util.Map;
@Component
public class CustomUserAuthenticationConverter extends DefaultUserAuthenticationConverter {
@Autowired
UserDetailsService userDetailsService;
@Override
public Map<String, ?> convertUserAuthentication(Authentication authentication) {
LinkedHashMap response = new LinkedHashMap();
String name = authentication.getName();
response.put("username", name);
Object principal = authentication.getPrincipal();
UserJwt userJwt = null;
if(principal instanceof UserJwt){
userJwt = (UserJwt) principal;
}else{
//refresh_token默认不去调用userdetailService获取用户信息,这里我们手动去调用,得到 UserJwt
UserDetails userDetails = userDetailsService.loadUserByUsername(name);
userJwt = (UserJwt) userDetails;
}
response.put("name", userJwt.getName());
response.put("id", userJwt.getId());
if (authentication.getAuthorities() != null && !authentication.getAuthorities().isEmpty()) {
response.put("authorities", AuthorityUtils.authorityListToSet(authentication.getAuthorities()));
}
return response;
}
}
package com.dongyimai.oauth.s.config;
import com.dongyimai.oauth.s.util.UserJwt;
import com.offcn.entity.Result;
import com.offcn.user.feign.UserFeign;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.oauth2.provider.ClientDetails;
import org.springframework.security.oauth2.provider.ClientDetailsService;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
/*****
* 自定义授权认证类
*/
@Service
public class UserDetailsServiceImpl implements UserDetailsService {
@Autowired
ClientDetailsService clientDetailsService;
@Autowired
UserFeign userFeign;
/****
* 自定义授权认证
* @param username
* @return
* @throws UsernameNotFoundException
*/
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
//取出身份,如果身份为空说明没有认证
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
//没有认证统一采用httpbasic认证,httpbasic中存储了client_id和client_secret,开始认证client_id和client_secret
if(authentication==null){
ClientDetails clientDetails = clientDetailsService.loadClientByClientId(username);
if(clientDetails!=null){
//秘钥
String clientSecret = clientDetails.getClientSecret();
//静态方式
//return new User(username,new BCryptPasswordEncoder().encode(clientSecret), AuthorityUtils.commaSeparatedStringToAuthorityList(""));
//数据库查找方式
return new User(username,clientSecret, AuthorityUtils.commaSeparatedStringToAuthorityList(""));
}
}
if (StringUtils.isEmpty(username)) {
return null;
}
// ********************************用户名和密码登录开始*****************************************
if (StringUtils.isEmpty(username)) {
System.out.println("----------------2222----------------------------");
return null;
}
System.out.println("username:"+username);
Result<com.offcn.user.dao.User> user = userFeign.findByUserName(username);
//执行查询数据库
System.out.println("username:"+user.getData().getUsername());
System.out.println("passsword:"+user.getData().getPassword());
String permissions="salesman,accountant,user";
System.out.println("permissions:"+permissions);
UserJwt userDetails = new UserJwt(username,user.getData().getPassword(), AuthorityUtils.commaSeparatedStringToAuthorityList(permissions));
//=======================用户账号和密码认证结束==========================
return userDetails;
/*//根据用户名查询用户信息
String pwd = new BCryptPasswordEncoder().encode("dongyimai");
//创建User对象
String permissions = "goods_list,seckill_list";
UserJwt userDetails = new UserJwt(username,pwd,AuthorityUtils.commaSeparatedStringToAuthorityList(permissions));
return userDetails;*/
}
}
package com.dongyimai.oauth.s.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
@Configuration
@EnableWebSecurity
@Order(-1)
class WebSecurityConfig extends WebSecurityConfigurerAdapter {
/***
* 忽略安全拦截的URL
* @param web
* @throws Exception
*/
@Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers(
"/oauth/login",
"/oauth/logout");
}
/***
* 创建授权管理认证对象
* @return
* @throws Exception
*/
@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
AuthenticationManager manager = super.authenticationManagerBean();
return manager;
}
/***
* 采用BCryptPasswordEncoder对密码进行编码
* @return
*/
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
/****
*
* @param http
* @throws Exception
*/
@Override
public void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.httpBasic() //启用Http基本身份验证
.and()
.formLogin() //启用表单身份验证
.and()
.authorizeRequests() //限制基于Request请求访问
.anyRequest()
.authenticated(); //其他请求都需要经过验证
}
}
package com.dongyimai.oauth.s.controller;
import com.dongyimai.oauth.s.service.AuthService;
import com.dongyimai.oauth.s.util.AuthToken;
import com.offcn.entity.Result;
import com.offcn.entity.StatusCode;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletResponse;
@RestController
@RequestMapping("/user")
public class AuthController {
// 客户端的ID
@Value("${auth.clientId}")
private String clientId;
@Value("${auth.clientSecret}")
private String clientSecret;
@Autowired
private AuthService authService;
@RequestMapping("/login")
public Result login(String username, String password, HttpServletResponse response){
// 数据验证
if(StringUtils.isEmpty(username)){
throw new RuntimeException("用户名不可以为空");
}
if(StringUtils.isEmpty(password)){
throw new RuntimeException("密码不可以为空");
}
// 创建认证令牌对象
AuthToken authToken = authService.login(username, password, clientId, clientSecret);
// 获取令牌
String token = authToken.getAccessToken();
// 创建Cookie
Cookie cookie = new Cookie("Authorization", token);
cookie.setDomain("localhost");
cookie.setPath("/");
response.addCookie(cookie);
return new Result(true, StatusCode.OK,"登录成功",token);
}
}
package com.dongyimai.oauth.s.interceptor;
import feign.RequestInterceptor;
import feign.RequestTemplate;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import java.util.Enumeration;
public class FeignInterceptor implements RequestInterceptor {
@Override
public void apply(RequestTemplate requestTemplate) {
try {
//使用RequestContextHolder工具获取request相关变量
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
if (attributes != null) {
//取出request
HttpServletRequest request = attributes.getRequest();
//获取所有头文件信息的key
Enumeration<String> headerNames = request.getHeaderNames();
if (headerNames != null) {
while (headerNames.hasMoreElements()) {
//头文件的key
String name = headerNames.nextElement();
//头文件的value
String values = request.getHeader(name);
//将令牌数据添加到头文件中
requestTemplate.header(name, values);
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
package com.dongyimai.oauth.s.service.impl;
import com.dongyimai.oauth.s.service.AuthService;
import com.dongyimai.oauth.s.util.AuthToken;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.util.Base64Utils;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.web.client.RestTemplate;
import java.util.Map;
@Service
public class AuthServiceImpl implements AuthService {
@Autowired
private LoadBalancerClient loadBalancerClient;
@Autowired
private RestTemplate restTemplate;
@Override
public AuthToken login(String username, String password, String clientId, String clientSecret) {
// 未来可能多有认证中心,获取认证中心的地址
ServiceInstance serviceInstance = loadBalancerClient.choose("user-auth");
if(serviceInstance == null){
throw new RuntimeException("没有认证中心的服务");
}
// 路径的获取
String path = serviceInstance.getUri().toString() + "/oauth/token";
// 定义表单的数据
LinkedMultiValueMap<String, String> formData = new LinkedMultiValueMap<>();
// 添加表单数据
formData.add("grant_type","password");
formData.add("username",username);
formData.add("password",password);
// 请求头的信息
LinkedMultiValueMap<String, String> header = new LinkedMultiValueMap<>();
header.add("Authorization",authMessage(clientId,clientSecret));
// 获取数据
ResponseEntity<Map> response = restTemplate.exchange(path, HttpMethod.POST, new HttpEntity<LinkedMultiValueMap<String, String>>(formData, header), Map.class);
Map body = response.getBody();
if(body == null || body.get("access_token") == null || body.get("refresh_token") == null || body.get("jti") == null){
throw new RuntimeException("返回的令牌有误");
}
// 设定返回结果
AuthToken authToken = new AuthToken();
authToken.setJti((String)body.get("jti"));
authToken.setAccessToken((String)body.get("access_token"));
authToken.setRefreshToken((String) body.get("refresh_token"));
return authToken;
}
private String authMessage(String clientId,String clientSecret){
String str = clientId + ":" + clientSecret;
// Base64 加密
byte[] encode = Base64Utils.encode(str.getBytes());
// 转换为String
return "Basic " + new String(encode);
}
}
// An highlighted block
var foo = 'bar';
package com.dongyimai.oauth.s.service;
import com.dongyimai.oauth.s.util.AuthToken;
public interface AuthService {
// 密码模式的授权认证
public AuthToken login(String username, String password, String clientId, String clientSecret);
}
package com.dongyimai.oauth.s.util;
import java.io.Serializable;
public class AuthToken implements Serializable{
//令牌信息
String accessToken;
//刷新token(refresh_token)
String refreshToken;
//jwt短令牌
String jti;
public String getAccessToken() {
return accessToken;
}
public void setAccessToken(String accessToken) {
this.accessToken = accessToken;
}
public String getRefreshToken() {
return refreshToken;
}
public void setRefreshToken(String refreshToken) {
this.refreshToken = refreshToken;
}
public String getJti() {
return jti;
}
public void setJti(String jti) {
this.jti = jti;
}
}
package com.dongyimai.oauth.s.util;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.HashMap;
import java.util.Map;
/**
* Created by admin on 2018/3/18.
*/
public class CookieUtil {
/**
* 设置cookie
*
* @param response
* @param name cookie名字
* @param value cookie值
* @param maxAge cookie生命周期 以秒为单位
*/
public static void addCookie(HttpServletResponse response, String domain, String path, String name,
String value, int maxAge, boolean httpOnly) {
Cookie cookie = new Cookie(name, value);
cookie.setDomain(domain);
cookie.setPath(path);
cookie.setMaxAge(maxAge);
cookie.setHttpOnly(httpOnly);
response.addCookie(cookie);
}
/**
* 根据cookie名称读取cookie
* @param request
* @return map<cookieName,cookieValue>
*/
public static Map<String,String> readCookie(HttpServletRequest request, String ... cookieNames) {
Map<String,String> cookieMap = new HashMap<String,String>();
Cookie[] cookies = request.getCookies();
if (cookies != null) {
for (Cookie cookie : cookies) {
String cookieName = cookie.getName();
String cookieValue = cookie.getValue();
for(int i=0;i<cookieNames.length;i++){
if(cookieNames[i].equals(cookieName)){
cookieMap.put(cookieName,cookieValue);
}
}
}
}
return cookieMap;
}
}
package com.dongyimai.oauth.s.util;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.User;
import java.util.Collection;
public class UserJwt extends User {
private String id; //用户ID
private String name; //用户名字
public UserJwt(String username, String password, Collection<? extends GrantedAuthority> authorities) {
super(username, password, authorities);
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
package com.dongyimai.oauth.s;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;
@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients(basePackages = {"com.offcn.user.feign"})
public class OAuthApplication {
public static void main(String[] args) {
SpringApplication.run(OAuthApplication.class,args);
}
@Bean
public RestTemplate getRestTemplate(){
return new RestTemplate();
}
}