Alamofire4 PUT、POSTbody传参以及实现Oauth2认证

       Alamofire是原AFNetworking团队针对Swift语言封装的网络请求库,相较于AF基本不存在内存泄漏的问题。最新版是Alamofire5最低支持系统为iOS10,具体可参考文章:Alamofire 5 的使用 - 基本用法。针对AF框架存在的内存泄漏解决方案,博客园有很多文章,尤其是文件、图片上传导致的内存泄漏。具体可参考:[AFHTTPSessionManager manager]内存泄漏解决

     下面就将Alamofire 在PUT、POST请求下body 传值以及图片、文件上传的调用简单二次封装列出如下,供参考和学习使用:

  • Alamofire PUT/POST方式请求,body传参实例:
/**!
     * post 接口请求
     * @para strUrl   String 请求地址
     * @para body     Data? 请求参数
     * @para successBack  成功回调
     * @para failureBack  失败回调
     */
    func postRequestWithBodyFor(strUrl:String,
                                withBody body:Data?,
                                AndSuccessBack successBack:@escaping SuccessBlock,
                                AndFailureBack failureBack:@escaping FailureBlock,
                                WithisLoading isLoading:Bool = true) {

        if body != nil {
             print("请求地址:\(strUrl),参数:\(NSString.init(data: body!, encoding: String.Encoding.utf8.rawValue) ?? "暂无参数")")
        }
        else{
            print("请求地址:\(strUrl),暂无参数")
        }

        if isLoading == true {
            SVProgressHUD.showLoading()
        }
        
        var request = URLRequest.init(url: URL.init(string: strUrl)!)
        request.httpBody = body
        request.httpMethod = "POST"
        request.timeoutInterval = K_APP_REQUEST_TIME_OUT
        request.setValue("application/json", forHTTPHeaderField: "Accept")
        request.setValue("application/json;charset=UTF-8", forHTTPHeaderField: "Content-Type")
        
        Alamofire.request(request)
                 .validate()
                 .validate(contentType: K_APP_ACCEPTABLE_CONTENTTYPES)
                 .responseJSON { response in
                
                    if isLoading == true {
                         SVProgressHUD.dismissLoading()
                      }

                      var msg:String? = response.error?.localizedDescription ?? "请求数据不存在"
                      self.errorHandle(Error: response.error as NSError?,
                                  statusCode: response.response?.statusCode,
                                 andErrormsg: &msg)
                      
                      print("请求结果:\(response)")
                      if response.error != nil {
                         failureBack(msg)
                      }
                      else{
                        if let jsonObj:[String:Any] = response.value as? [String:Any] {
                            
                            var code:Int? = jsonObj[K_API_RESULT_CODE] as? Int
                            if code == nil, let strTemp = jsonObj[K_API_RESULT_CODE] as? String {
                                code = NSNumber.init(string:strTemp)?.intValue
                            }
                            
                            //请求成功
                            if K_API_IS_OK(rs: code) {
                                successBack(jsonObj[K_API_RESULT_DATA] is NSNull ? nil : jsonObj[K_API_RESULT_DATA])
                            }
                            //京东AI拍照识别
                            else if code == 10000 {
                                successBack(jsonObj["result"] is NSNull ? nil : jsonObj["result"])
                            }
                            else if code == 200 {
                                successBack(jsonObj[K_API_RESULT_DATA] is NSNull ? nil : jsonObj[K_API_RESULT_DATA])
                            }
                            else{
                               failureBack("\(jsonObj[K_API_RESULT_MESSAGE] ?? "请求失败")")
                           }
                        }
                        else{
                            failureBack(msg)
                        }
                    }
        }
    }
  • Alamofire实现OAuth Password 网络请求案例:
///  OAuth Password 网络请求
    ///  https://github.com/AFNetworking/AFOAuth2Manager
    /// - Parameters:
    ///   - un: 用户名
    ///   - pwd: 密码
    ///   - successBack: 成功回调
    ///   - failureBack: 失败回调
    ///   - isLoading: 是否显示加载
    func oAuthRequestPasswordFor(Username un:String,
                                 andPwd pwd:String,
                                 andSuccessBack successBack:@escaping SuccessBlock,
                                 andFailureBack failureBack:@escaping FailureBlock,
                                 withisLoading isLoading:Bool = true){
        
        print("请求参数:\(un),\(pwd)")
        
        let strUrl = String.init(format:"%@oauth/token",K_APP_OAUTH_HOST)

        if isLoading == true {
           SVProgressHUD.showLoading()
        }
        
        let dicParam = [
            "username": un,
            "password": pwd,
            "grant_type":"password",
            "client_id":K_APP_IS_PRODUCT ? K_APP_CLIENT_ID_PRO : K_APP_CLIENT_ID_DEV,
            "client_secret":K_APP_IS_PRODUCT ? K_APP_CLIENT_SECRET_PRO : K_APP_CLIENT_SECRET_DEV
        ]
        
        Alamofire.request(strUrl,
                          method: .post,
                      parameters: dicParam)
                 .validate()
                 .responseJSON { response in

                    if isLoading == true {
                        SVProgressHUD.dismissLoading()
                    }
                    
                    var msg:String? = response.error?.localizedDescription ?? "请求数据不存在"
                    self.errorHandle(Error: response.error as NSError?,
                                     statusCode: response.response?.statusCode,
                                     andErrormsg: &msg)
                    
                    print("请求结果:\(response)")
                    if response.error != nil {
                        failureBack(msg)
                    }
                    else{
                        if let jsonObj:[String:Any] = response.value as? [String:Any] {
                            let access_token:String? = jsonObj[UserModel.k_user_tooken] as? String
                            if access_token == nil || access_token == "" {
                                failureBack("用户名或密码错误")
                            }
                            else{
                                //请求成功
                                successBack(access_token)
                            }
                        }
                        else{
                            failureBack("请求token不存在")
                        }
                    }
        }
    }
  • Alamofire文件或图片上传,参考案例:
/**!
     * 文件或图片上传
     * @para strUrl String 上传地址
     * @para uploadformDataBack 上传参数设置
     * @para successBack  成功回调
     * @para failureBack  失败回调
     */
    func postImageUploadToServer(strUrl:String,
                                 uploadformDataBack:@escaping(_ fData:MultipartFormData)->(Void),
                                 AndSuccessBack successBack:@escaping SuccessBlock,
                                 AndFailureBack failureBack:@escaping FailureBlock,
                                 WithisLoading isLoading:Bool = true){
        
        print("上传地址:\(strUrl)")

        if isLoading == true {
            SVProgressHUD.showLoading()
        }
        
        Alamofire.upload(multipartFormData: { (_multipartFormData:MultipartFormData) in
             //指定参数
             uploadformDataBack(_multipartFormData)
        },
            to: strUrl) { encodingResult in
                            
                            if isLoading == true {
                               SVProgressHUD.dismissLoading()
                            }
                            
                            switch(encodingResult){
                            case .success(let upload,_,_):
                                upload.responseJSON { response in
                                    print("上传结果:\(response)")
                                    
                                    let result = response.result
                                    if result.isSuccess {
                                        if let jsonObj:[String:Any] = response.value as? [String:Any] {
                                               //请求成功
                                               if K_API_IS_OK(rs: jsonObj[K_API_RESULT_CODE]) || jsonObj[K_API_RESULT_CODE] as? Int == 200 {
                                                   successBack(jsonObj[K_API_RESULT_DATA] is NSNull ? Any.self : jsonObj[K_API_RESULT_DATA])
                                               }
                                               else{
                                                  failureBack("\(jsonObj[K_API_RESULT_MESSAGE] ?? "请求失败")")
                                              }
                                           }
                                        else{
                                           failureBack("请求数据不存在")
                                        }
                                    }
                                    else{
                                        failureBack("请求数据不存在")
                                    }
                                }
                                      .validate()
                                break
                            case .failure(let error):
                                failureBack("\(error.localizedDescription)")
                                break
                            }
        }
    }

备注:

经过实际使用测试在Alamofire4(V4.9.1.1)中,由于请求的参数为Option可选类型,会导致部分请求失败,此情况下需要将参数使用"!"或"guard"进行强制拆包。

Alamofire 使用CocoaPods导入到项目等操作知识点,请自行查找资料。

如上案例部分私有方法,参考如下:

import Alamofire.Swift
import SVProgressHUD
typealias SuccessBlock = (_ responseData:Any?) -> (Void)
typealias FailureBlock = (_ responseString:String?) -> (Void)
    
    
    //MARK: - errorHandle
    private func errorHandle(Error e:NSError?,
                             statusCode:Int?,
                             andErrormsg ems:inout String?) {
        let code:Int? = e?.code
        print("error code:\(code ?? 0)")
        
        //https://www.jb51.net/article/105163.htm
        switch statusCode {
        case .some(302):
            ems = "请求被重定向"
            
        case .some(400):
            ems = "发送的请求有语法错误"
            
        case .some(401):
            ems = "访问没有授权"
            
        case .some(403):
            ems = "没有权限访问"
           
        case .some(404):
            ems = "请求地址不存在"
            
        case .some(405):
            ems = "请求方式不存在"
            
        case .some(408),.some(504):
            ems = "请求超时,请检查网络或重试"
            
        case .some(500):
            ems = "服务器内部异常,无法完成请求处理"
            
        case .some(507):
            ems = "服务器无法存储完成请求所必须的内容"
            
        case .some(509):
            ems = "服务器达到带宽限制"
            
        case .some(510):
            ems = "获取资源所需要的策略并没有没满足"
            
        default:
            break
        }
        
        switch code {
        case .some(-1001):
            ems = "请求超时"
            
        //token 过期
        case .some(-1011),.some(3):
            if statusCode == 401 {
                //...
            }
            
        case .some(-32700):
            ems = "类型转换错误"
            
        case .some(-32600):
            ems = "无效的请求"
            
        case .some(-32601):
            ems = "没有找到方法"
            
        case .some(-32602):
            ems = "无效的参数"
            
        case .some(-32603):
            ems = "网络异常,请检查网络"
            
        default:
            break
        }
    }
/** 网络请求状态判断(0 成功) */
func K_API_IS_OK(rs:Any?) -> Bool {
    guard let _rt:Int = rs as? Int else {
        return false
    }
    
    return _rt == 0
}

 

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
OAuth2是一种授权协议,用于授权第三方应用程序访问用户资源。Spring Security是一个强大的安全框架,可以与OAuth2协议一起使用来构建安全的应用程序。Spring Boot框架可以轻松地构建基于Spring Security和OAuth2的认证服务器。 下面是实现Spring Boot OAuth2认证服务器的步骤: 1. 添加Spring Security和OAuth2依赖项。在pom.xml文件中添加以下依赖项: ```xml <dependency> <groupId>org.springframework.security.oauth</groupId> <artifactId>spring-security-oauth2</artifactId> <version>2.4.0.RELEASE</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> ``` 2. 配置Spring Security。创建一个SecurityConfig类,继承WebSecurityConfigurerAdapter,并覆盖configure方法: ```java @Configuration @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { @Autowired private UserDetailsService userDetailsService; @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth.userDetailsService(userDetailsService); } @Override protected void configure(HttpSecurity http) throws Exception { http.csrf().disable() .authorizeRequests() .antMatchers("/oauth/token").permitAll() .anyRequest().authenticated() .and() .httpBasic(); } @Bean public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); } } ``` 这里定义了一个UserDetailsService来获取用户信息,并使用BCryptPasswordEncoder来加密密码。configure方法定义了认证和授权的规则,这里允许访问/oauth/token路径。 3. 配置OAuth2。创建一个AuthorizationServerConfig类,继承AuthorizationServerConfigurerAdapter,并覆盖configure方法: ```java @Configuration @EnableAuthorizationServer public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter { @Autowired private AuthenticationManager authenticationManager; @Autowired private UserDetailsService userDetailsService; @Autowired private DataSource dataSource; @Autowired private PasswordEncoder passwordEncoder; @Override public void configure(ClientDetailsServiceConfigurer clients) throws Exception { clients.jdbc(dataSource).passwordEncoder(passwordEncoder); } @Override public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception { endpoints.authenticationManager(authenticationManager) .userDetailsService(userDetailsService); } } ``` 这里使用了JDBC存储客户端信息和令牌,使用PasswordEncoder来加密客户端密码。configure方法定义了授权服务器的配置,包括客户端信息、令牌存储方式、身份验证管理器和用户详细信息服务。 4. 配置数据源。在application.properties文件中配置数据源,例如使用MySQL数据库: ``` spring.datasource.url=jdbc:mysql://localhost:3306/oauth2?useSSL=false spring.datasource.username=root spring.datasource.password=123456 spring.datasource.driver-class-name=com.mysql.jdbc.Driver ``` 5. 测试OAuth2认证服务器。启动应用程序并访问/oauth/token路径,可以获取访问令牌。例如: ``` curl -X POST \ http://localhost:8080/oauth/token \ -H 'Authorization: Basic Y2xpZW50OnNlY3JldA==' \ -H 'Content-Type: application/x-www-form-urlencoded' \ -d 'grant_type=password&username=user&password=password' ``` 这里使用了基本身份验证来验证客户端,用户名为client,密码为secret。授权类型为密码,用户名为user,密码为password。成功获取访问令牌后,可以使用该令牌来访问需要授权的资源。 以上就是使用Spring Boot实现OAuth2认证服务器的步骤。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

追夢秋陽

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值