A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

4.3.4 申请令牌测试
为了不破坏Spring Security的代码,我们在Service方法中通过RestTemplate请求Spring Security所暴露的申请令 牌接口来申请令牌,下边是测试代码:
@SpringBootTest @RunWith(SpringRunner.class) public class TestClient {   
   @Autowired   
LoadBalancerClient loadBalancerClient;      
@Autowired  
   RestTemplate restTemplate;  
     @Test     
public void testClient(){   
       //采用客户端负载均衡,从eureka获取认证服务的ip 和端口   
      ServiceInstance serviceInstance =  loadBalancerClient.choose(XcServiceList.XC_SERVICE_UCENTER_AUTH);        
URI uri = serviceInstance.getUri();
        String authUrl = uri+"/auth/oauth/token";

[AppleScript] 纯文本查看 复制代码
   
    //URI url, HttpMethod method, HttpEntity<?> requestEntity, Class<T> responseType   
     // url就是 申请令牌的url /oauth/token      
   //method http的方法类型 
        //requestEntity请求内容 
        //responseType,将响应的结果生成的类型    
       //请求的内容分两部分     
    //1、header信息,包括了http basic认证信息 
        MultiValueMap<String, String> headers = new LinkedMultiValueMap<String, String>();     
    String httpbasic = httpbasic("XcWebApp", "XcWebApp");   
      //"Basic WGNXZWJBcHA6WGNXZWJBcHA="    
     headers.add("Authorization", httpbasic);    
     //2、包括:grant_type、username、passowrd     
    MultiValueMap<String, String> body = new LinkedMultiValueMap<String, String>();   
      body.add("grant_type","password");        
 body.add("username","itcast");      
   body.add("password","123");      
   HttpEntity<MultiValueMap<String, String>> multiValueMapHttpEntity = new  HttpEntity<MultiValueMap<String, String>>(body, headers); //指定 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);         
        }         
    }      
   });   
      //远程调用申请令牌      
   ResponseEntity<Map> exchange = restTemplate.exchange(authUrl, HttpMethod.POST,  multiValueMapHttpEntity, Map.class);           Map body1 = exchange.getBody();     
    System.out.println(body1);   
    }       private String httpbasic(String clientId,String clientSecret){    
       //将客户端id和客户端密码拼接,按“客户端id:客户端密码”  
       String string = clientId+":"+clientSecret;     
    //进行base64编码   
      byte[] encode = Base64.encode(string.getBytes());    
     return "Basic "+new String(encode);     } }

4.3.4 Dao
暂时使用静态数据,待用户登录调通再连接数据库校验用户信息。

4.3.5 Service
调用认证服务申请令牌,并将令牌存储到 redis。
1、AuthToken
创建 AuthToken模型类,存储申请的令牌,包括身份令牌、刷新令牌、jwt令牌
身份令牌:用于校验用户是否认证
刷新令牌:jwt令牌快过期时执行刷新令牌 jwt令牌:用于授权

[AppleScript] 纯文本查看 复制代码
@Data @ToString @NoArgsConstructor public class AuthToken {  
   String access_token;//身份token     
String refresh_token;//刷新token  
   String jwt_token;//jwt令牌 }

申请令牌的service方法如下:

[AppleScript] 纯文本查看 复制代码
@Service public class AuthService {    
   private static final Logger LOGGER = LoggerFactory.getLogger(AuthService.class);     
  @Value("${auth.tokenValiditySeconds}")   
  int tokenValiditySeconds;    
   @Autowired   
  RestTemplate restTemplate;     
@Autowired  
   LoadBalancerClient loadBalancerClient;    
 @Autowired  
   StringRedisTemplate stringRedisTemplate;   
    //认证方法    
 public AuthToken login(String username,String password,String clientId,String clientSecret){    
     //申请令牌       
  AuthToken authToken = applyToken(username,password,clientId, clientSecret);   
      if(authToken == null){   
          ExceptionCast.cast(AuthCode.AUTH_LOGIN_APPLYTOKEN_FAIL);   
      }         //将 token存储到redis     
    String access_token = authToken.getAccess_token();        
 String content = JSON.toJSONString(authToken);    
     boolean saveTokenResult = saveToken(access_token, content, tokenValiditySeconds);
        if(!saveTokenResult){

[AppleScript] 纯文本查看 复制代码
 ExceptionCast.cast(AuthCode.AUTH_LOGIN_TOKEN_SAVEFAIL);   
      }   
      return authToken;  
   }  
   //存储令牌到redis  
   private boolean saveToken(String access_token,String content,long ttl){    
     //令牌名称   
      String name = "user_token:" + access_token;       
  //保存到令牌到redis      
   stringRedisTemplate.boundValueOps(name).set(content,ttl, TimeUnit.SECONDS);    
     //获取过期时间         Long expire = stringRedisTemplate.getExpire(name);      
   return expire>0;  
   }   
  //认证方法     
private AuthToken applyToken(String username,String password,String clientId,String  clientSecret){   
      //选中认证服务的地址      
   ServiceInstance serviceInstance =  loadBalancerClient.choose(XcServiceList.XC_SERVICE_UCENTER_AUTH);   
      if (serviceInstance == null) {       
      LOGGER.error("choose an auth instance fail");     
        ExceptionCast.cast(AuthCode.AUTH_LOGIN_AUTHSERVER_NOTFOUND);    
     }       
  //获取令牌的url       
  String path = serviceInstance.getUri().toString()+"/auth/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, 

[AppleScript] 纯文本查看 复制代码
new HttpEntity<MultiValueMap<String, String>>(formData, header), Map.class);          
   map = mapResponseEntity.getBody();     
      } catch (RestClientException e) {          
   e.printStackTrace();      
       LOGGER.error("request oauth_token_password error: {}",e.getMessage());      
       e.printStackTrace();       
      ExceptionCast.cast(AuthCode.AUTH_LOGIN_APPLYTOKEN_FAIL);   
      }           if(map == null ||           
      map.get("access_token") == null ||        
         map.get("refresh_token") == null ||        
         map.get("jti") == null){//jti是jwt令牌的唯一标识作为用户身份令牌        
     ExceptionCast.cast(AuthCode.AUTH_LOGIN_APPLYTOKEN_FAIL);    
     }    
     AuthToken authToken = new AuthToken();   
      //访问令牌(jwt)  
       String jwt_token = (String) map.get("access_token");     
    //刷新令牌(jwt)   
      String refresh_token = (String) map.get("refresh_token");    
     //jti,作为用户的身份标识     
    String access_token = (String) map.get("jti");     
    authToken.setJwt_token(jwt_token);       
  authToken.setAccess_token(access_token);   
      authToken.setRefresh_token(refresh_token);       
  return authToken;   
  }     
  //获取httpbasic认证串    private String httpbasic(String clientId,String clientSecret){    
       //将客户端id和客户端密码拼接,按“客户端id:客户端密码”   
      String string = clientId+":"+clientSecret;  
       //进行base64编码    
     byte[] encode = Base64.encode(string.getBytes());     
    return "Basic "+new String(encode); 
    } } 


0 个回复

您需要登录后才可以回帖 登录 | 加入黑马