ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

transfer auth2

2021-11-13 22:30:41  阅读:149  来源: 互联网

标签:令牌 return String transfer param auth2 new public


代码:

AuthorizationServerConfig

@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());
  /*  clients.inMemory()
            .withClient("changgou")          //客户端id
            .secret("changgou")                      //秘钥
            .redirectUris("http://localhost")       //重定向地址
            .accessTokenValiditySeconds(3600)          //访问令牌有效期
            .refreshTokenValiditySeconds(3600)         //刷新令牌有效期
            .authorizedGrantTypes(
                    "authorization_code",          //根据授权码生成令牌
                    "client_credentials",          //客户端认证
                    "refresh_token",                //刷新令牌
                    "password")                     //密码方式认证
            .scopes("app");                         //客户端范围,名称自定义,必填*/
}

/***
 * 授权服务器端点配置
 * @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);
}

JwtAccessTokenConverter
/****
* JWT令牌转换器
* @param customUserAuthenticationConverter
* @return
*/
@Bean
public JwtAccessTokenConverter jwtAccessTokenConverter(CustomUserAuthenticationConverter customUserAuthenticationConverter) {
JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
KeyPair keyPair = new KeyStoreKeyFactory(
keyProperties.getKeyStore().getLocation(), //证书路径 changgou.jks
keyProperties.getKeyStore().getSecret().toCharArray()) //证书秘钥 changgouapp
.getKeyPair(
keyProperties.getKeyStore().getAlias(), //证书别名 changgou
keyProperties.getKeyStore().getPassword().toCharArray()); //证书密码 changgou
converter.setKeyPair(keyPair);
//配置自定义的CustomUserAuthenticationConverter
DefaultAccessTokenConverter accessTokenConverter = (DefaultAccessTokenConverter) converter.getAccessTokenConverter();
accessTokenConverter.setUserTokenConverter(customUserAuthenticationConverter);
return converter;
}
}

@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());
    //公司 response.put("compy", "songsi");
    if (authentication.getAuthorities() != null && !authentication.getAuthorities().isEmpty()) {
        response.put("authorities", AuthorityUtils.authorityListToSet(authentication.getAuthorities()));
    }
    return response;
}

}
UserDetailsServiceImpl
@Service
public class UserDetailsServiceImpl implements UserDetailsService {

@Autowired
ClientDetailsService clientDetailsService;

@Autowired
private 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;
    }

    //根据用户名查询用户信息
    //String pwd = new BCryptPasswordEncoder().encode("szitheima");
    String pwd = userFeign.findByUsername(username).getData().getPassword();
    //创建User对象  授予权限.GOODS_LIST  SECKILL_LIST
    String permissions = "goods_list,seckill_list";
    UserJwt userDetails = new UserJwt(username,pwd,AuthorityUtils.commaSeparatedStringToAuthorityList(permissions));
    //userDetails.setComy(songsi);
    return userDetails;
}
public static void main(String[] args) {
    String zhangsan = new BCryptPasswordEncoder().encode("zhangsan");
    System.out.println(zhangsan);
}

}

WebSecurityConfig
@Configuration
@EnableWebSecurity
@Order(-1)
class WebSecurityConfig extends WebSecurityConfigurerAdapter {

/***
 * 忽略安全拦截的URL
 * @param web
 * @throws Exception
 */
@Override
public void configure(WebSecurity web) throws Exception {
    web.ignoring().antMatchers(
            "/user/login",
            "/user/logout","/oauth/login","/css/**","/data/**","/fonts/**","/img/**","/js/**");
}

/***
 * 创建授权管理认证对象
 * @return
 * @throws Exception
 */
@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
    AuthenticationManager manager = super.authenticationManagerBean();
    return manager;
}

@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    super.configure(auth);
}

/***
 * 采用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()       //启用表单身份验证
            .loginPage("/oauth/login")
            .loginProcessingUrl("/user/login")
            .and()
            .authorizeRequests()    //限制基于Request请求访问
            .anyRequest()
            .authenticated();       //其他请求都需要经过验证
}

}

AuthController
/*****

  • @Author: www.itheima

  • @Date: 2019/7/7 16:42

  • @Description: com.changgou.oauth.controller
    ****/
    @RestController
    @RequestMapping(value = “/userx”)
    public class AuthController {

    //客户端ID
    @Value("${auth.clientId}")
    private String clientId;

    //秘钥
    @Value("${auth.clientSecret}")
    private String clientSecret;

    //Cookie存储的域名
    @Value("${auth.cookieDomain}")
    private String cookieDomain;

    //Cookie生命周期
    @Value("${auth.cookieMaxAge}")
    private int cookieMaxAge;

    @Autowired
    AuthService authService;

    @PostMapping("/login")
    public Result login(String username, String password) {
    if(StringUtils.isEmpty(username)){
    throw new RuntimeException(“用户名不允许为空”);
    }
    if(StringUtils.isEmpty(password)){
    throw new RuntimeException(“密码不允许为空”);
    }
    //申请令牌
    AuthToken authToken = authService.login(username,password,clientId,clientSecret);

     //用户身份令牌
     String access_token = authToken.getAccessToken();
     //将令牌存储到cookie
     saveCookie(access_token);
    
     return new Result(true, StatusCode.OK,"登录成功!");
    

    }

    /***

    • 将令牌存储到cookie
    • @param token
      */
      private void saveCookie(String token){
      HttpServletResponse response = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse();
      CookieUtil.addCookie(response,cookieDomain,"/",“Authorization”,token,cookieMaxAge,false);
      }
      }

LoginRedirectController
@Controller
@RequestMapping("/oauth")
public class LoginRedirectController {

@RequestMapping("/login")
public String login(String From, Model model) {
    model.addAttribute("from",From);
    return "login";
}

}

AuthServiceImpl
@Service
public class AuthServiceImpl implements AuthService {

@Autowired
private LoadBalancerClient loadBalancerClient;

@Autowired
private RestTemplate restTemplate;

/***
 * 授权认证方法
 * @param username
 * @param password
 * @param clientId
 * @param clientSecret
 * @return
 */
@Override
public AuthToken login(String username, String password, String clientId, String clientSecret) {
    //申请令牌
    AuthToken authToken = applyToken(username,password,clientId, clientSecret);
    if(authToken == null){
        throw new RuntimeException("申请令牌失败");
    }
    return authToken;
}


/****
 * 认证方法
 * @param username:用户登录名字
 * @param password:用户密码
 * @param clientId:配置文件中的客户端ID
 * @param clientSecret:配置文件中的秘钥
 * @return
 */
private AuthToken applyToken(String username, String password, String clientId, String clientSecret) {
    //选中认证服务的地址
    ServiceInstance serviceInstance = loadBalancerClient.choose("user-auth");
    if (serviceInstance == null) {
        throw new RuntimeException("找不到对应的服务");
    }
    //获取令牌的url
    String path = serviceInstance.getUri().toString() + "/oauth/token";
    //定义body
    MultiValueMap<String, String> formData = new LinkedMultiValueMap<>();
    //授权方式
    formData.add("grant_type", "password");
    //账号
    formData.add("username", username);
    //密码
    formData.add("password", password);
    //定义头
    MultiValueMap<String, String> header = new LinkedMultiValueMap<>();
    header.add("Authorization", httpbasic(clientId, clientSecret));
    //指定 restTemplate当遇到400或401响应时候也不要抛出异常,也要正常返回值
    restTemplate.setErrorHandler(new DefaultResponseErrorHandler() {
        @Override
        public void handleError(ClientHttpResponse response) throws IOException {
            //当响应的值为400或401时候也要正常响应,不要抛出异常
            if (response.getRawStatusCode() != 400 && response.getRawStatusCode() != 401) {
                super.handleError(response);
            }
        }
    });
    Map map = null;
    try {
        //http请求spring security的申请令牌接口
        ResponseEntity<Map> mapResponseEntity = restTemplate.exchange(path, HttpMethod.POST,new HttpEntity<MultiValueMap<String, String>>(formData, header), Map.class);
        //获取响应数据
        map = mapResponseEntity.getBody();
    } catch (RestClientException e) {
        throw new RuntimeException(e);
    }
    if(map == null || map.get("access_token") == null || map.get("refresh_token") == null || map.get("jti") == null) {
        //jti是jwt令牌的唯一标识作为用户身份令牌
        throw new RuntimeException("创建令牌失败!");
    }

    //将响应数据封装成AuthToken对象
    AuthToken authToken = new AuthToken();
    //访问令牌(jwt)
    String accessToken = (String) map.get("access_token");
    //刷新令牌(jwt)
    String refreshToken = (String) map.get("refresh_token");
    //jti,作为用户的身份标识
    String jwtToken= (String) map.get("jti");
    authToken.setJti(jwtToken);
    authToken.setAccessToken(accessToken);
    authToken.setRefreshToken(refreshToken);
    return authToken;
}


/***
 * base64编码
 * @param clientId
 * @param clientSecret
 * @return
 */
private String httpbasic(String clientId,String clientSecret){
    //将客户端id和客户端密码拼接,按“客户端id:客户端密码”
    String string = clientId+":"+clientSecret;
    //进行base64编码
    byte[] encode = Base64Utils.encode(string.getBytes());
    return "Basic "+new String(encode);
}

}

LoginServiceImpl
@Service
public class LoginServiceImpl implements LoginService {

@Autowired
private RestTemplate restTemplate;

@Autowired
private LoadBalancerClient loadBalancerClient;

@Override
public AuthToken login(String username, String password, String clientId, String clientSecret, String grandType) {

    //1.定义url (申请令牌的url)
    //参数 : 微服务的名称spring.appplication指定的名称
    ServiceInstance choose = loadBalancerClient.choose("user-auth");
    String url =choose.getUri().toString()+"/oauth/token";

    //2.定义头信息 (有client id 和client secr)
    MultiValueMap<String,String> headers = new LinkedMultiValueMap<>();
    headers.add("Authorization","Basic "+Base64.getEncoder().encodeToString(new String(clientId+":"+clientSecret).getBytes()));
    //3. 定义请求体  有授权模式 用户的名称 和密码
    MultiValueMap<String,String> formData = new LinkedMultiValueMap<>();
    formData.add("grant_type",grandType);
    formData.add("username",username);
    formData.add("password",password);
    //4.模拟浏览器 发送POST 请求 携带 头 和请求体 到认证服务器

    /**
     * 参数1  指定要发送的请求的url
     * 参数2  指定要发送的请求的方法 PSOT
     * 参数3 指定请求实体(包含头和请求体数据)
     */
    HttpEntity<MultiValueMap> requestentity = new HttpEntity<MultiValueMap>(formData,headers);

    ResponseEntity<Map> responseEntity = restTemplate.exchange(url, HttpMethod.POST, requestentity, Map.class);
    //5.接收到返回的响应(就是:令牌的信息)
    Map body = responseEntity.getBody();

    //封装一次.

    AuthToken authToken = new AuthToken();
    //访问令牌(jwt)
    String accessToken = (String) body.get("access_token");
    //刷新令牌(jwt)
    String refreshToken = (String) body.get("refresh_token");
    //jti,作为用户的身份标识
    String jwtToken= (String) body.get("jti");


    authToken.setJti(jwtToken);
    authToken.setAccessToken(accessToken);
    authToken.setRefreshToken(refreshToken);


    //6.返回
    return authToken;
}


public static void main(String[] args) {
    byte[] decode = Base64.getDecoder().decode(new String("Y2hhbmdnb3UxOmNoYW5nZ291Mg==").getBytes());
    System.out.println(new String(decode));
}

}

public interface AuthService {

/***
 * 授权认证方法
 */
AuthToken login(String username, String password, String clientId, String clientSecret);

}

public interface LoginService {
/**
* 模拟用户的行为 发送请求 申请令牌 返回
* @param username
* @param password
* @param clientId
* @param clientSecret
* @param grandType
* @return
*/
AuthToken login(String username, String password, String clientId, String clientSecret, String grandType);
}
AuthToken
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;
}

}

CookieUtil
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;
}

}

OAuthApplication

@SpringBootApplication
@EnableDiscoveryClient
@MapperScan(basePackages = “com.changgou.auth.dao”)
@EnableFeignClients(basePackages = {“com.changgou.user.feign”})
public class OAuthApplication {

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


@Bean(name = "restTemplate")
public RestTemplate restTemplate() {
    return new RestTemplate();
}

}

Pom.xml

<?xml version="1.0" encoding="UTF-8"?>



changgou-parent
com.changgou
1.0-SNAPSHOT

4.0.0
changgou-user-oauth

OAuth2.0认证环境搭建

<dependencies>
    <!--查询数据库数据-->
    <dependency>
        <groupId>com.changgou</groupId>
        <artifactId>changgou-common-db</artifactId>
        <version>1.0-SNAPSHOT</version>
    </dependency>

    <dependency>
        <groupId>org.springframework.security</groupId>
        <artifactId>spring-security-data</artifactId>
    </dependency>

    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-oauth2</artifactId>
    </dependency>

    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-security</artifactId>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-actuator</artifactId>
    </dependency>

    <dependency>
        <groupId>com.changgou</groupId>
        <artifactId>changgou-service-user-api</artifactId>
        <version>1.0-SNAPSHOT</version>
    </dependency>

    <!--thymleaf的依赖-->

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-thymeleaf</artifactId>
    </dependency>

</dependencies>

application.yml

server:
port: 9001
spring:
application:
name: user-auth
redis:
host: 192.168.211.132
port: 6379
password:
jedis:
pool:
max-active: 8
max-idle: 8
min-idle: 0
datasource:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://192.168.211.132:3306/changgou_oauth?useUnicode=true&characterEncoding=utf-8&useSSL=false&allowMultiQueries=true&serverTimezone=UTC
username: root
password: 123456
main:
allow-bean-definition-overriding: true
thymeleaf:
cache: false
eureka:
instance:
prefer-ip-address: true
client:
service-url:
defaultZone: http://127.0.0.1:7001/eureka
auth:
ttl: 3600 #token存储到redis的过期时间
clientId: changgou
clientSecret: changgou
cookieDomain: localhost
cookieMaxAge: -1
encrypt:
key-store:
location: classpath:/changgou.jks
secret: changgou
alias: changgou
password: changgou

脚本:
申请授权码
GET
http://localhost:9001/oauth/authorize?client_id=changgou&response_type=code&scop=app&redirect_uri=http://localhost

根据授权码获取token
POST
http://localhost:9001/oauth/token
Authorization: username password (Basic Auth)
form-data:
grant_type authorization_code
Code kKghj4
redirect_uri http://localhost

刷新令牌:
POST
http://localhost:9001/oauth/token?grant_type=refresh_token&refresh_token=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzY29wZSI6WyJhcHAiXSwiYXRpIjoiMjNmYTQwOGEtYzkyMi00NDdmLTk3OTktNjY2NjEzNjEwNTM5IiwibmFtZSI6bnVsbCwiaWQiOm51bGwsImV4cCI6MTYzNDQ4OTA4MCwiYXV0aG9yaXRpZXMiOlsic2Vja2lsbF9saXN0IiwiZ29vZHNfbGlzdCJdLCJqdGkiOiI0ZjU3MWU5ZS05MGMxLTQ0YzMtOTI1ZS05OTRjODQ4MmQ2OWMiLCJjbGllbnRfaWQiOiJjaGFuZ2dvdSIsInVzZXJuYW1lIjoic3ppdGhlaW1hIn0.MdkCkvQidZ2kJ6YC45-JDtr1sMSRmlEAZH5Vj3IkgLxvLFf5mktPqYMMFLS5K5yut53G5gBRCy792ZYbkC0sT-y5tHAnpGrTwLJPG6ZUI8dr5t2UotX4xDv_zlo4DQiUfmG2kBD8hKQeBaa6Y5WdWndfq11sNmdwZzFIBkGsgT-I15IXtx3UEL5y-kMQ30xpBJG_OlGE9y8RCi1H0Xa-kEPNVvkqYWwawW9mBgasH57yeYTEWYhgVCmYmLV3YZdQOu58JqwHKcFeUwUSya77m2Rr157uOZjxTk3tSoBtUAqLivJNU8XmRAxT5UIU4S5Sv7Egzm3uHjL7LWLKuCZ40g

令牌校验:
POST
http://localhost:9001/oauth/check_token?token=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzY29wZSI6WyJhcHAiXSwibmFtZSI6bnVsbCwiaWQiOm51bGwsImV4cCI6MTYzNDQ4OTA4MCwiYXV0aG9yaXRpZXMiOlsic2Vja2lsbF9saXN0IiwiZ29vZHNfbGlzdCJdLCJqdGkiOiIyM2ZhNDA4YS1jOTIyLTQ0N2YtOTc5OS02NjY2MTM2MTA1MzkiLCJjbGllbnRfaWQiOiJjaGFuZ2dvdSIsInVzZXJuYW1lIjoic3ppdGhlaW1hIn0.BlU5X5ZkJWq0X-AT1Qjg3eRkhvBvtgqpkW6twqn1sM0diXxjlxoZsOJspqHDFlbg2nrgv0uGMohEOhd8-1tLTZyttCTCqRaEkIsx-8u-vQmhmk9WqguGTjXKWZZhYAiXhlfg4SntMiAHYGmSyhoXAaH8GKifQb6Kyp-ChSAvAnwKzkQKNoMdXVTNyGlEn70ZCXw8gMwyJT9DH1Tr3o-sjyZ9Cq6uk4xMC7u-rypgJp2DsedCQo9wh5QH4PlD-QzqJq9FWsPFJnLptDYcXg9wIPRzmQnT33QqG9pDMHo2gCXuIa3oZlTylWcwFyt9ERohafZcbGvQQemp5kwEgQnjDQ

http://localhost:9001/oauth/token
Post
Formdata:
grant_type password
Username szitheima
Password szitheima

标签:令牌,return,String,transfer,param,auth2,new,public
来源: https://blog.csdn.net/qq_26496877/article/details/121311352

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有