购买应用时Google Play未经许可的响应

时间:2017-09-03 12:00:07

标签: android google-play licensing verification android-lvl

我的Android应用程序实现了LVL,并在启动时检查有效的许可证。我正在使用ServerManagedPolicy。每当我使用测试帐户,或者从Play商店购买应用程序时,都会给出未经许可的响应,并且我的用户非常恼火。

相关代码:

package controller;


import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import org.apache.tomcat.util.log.SystemLogHandler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import domain.Account;
import repo.AccountRepository;


@RestController
public class MyService {

    @Autowired
    private AccountRepository accountRepository;


    @RequestMapping(value = "/api", method = RequestMethod.GET)
    @CrossOrigin(origins = {"*"})
    public ResponseEntity<?> index(@RequestParam(value="name", required=false, defaultValue="admin1") String name) throws Exception {
            Account acc = accountRepository.findByUsername(name);
            return new ResponseEntity<>(acc, HttpStatus.OK);
    }




    @RequestMapping(value = "/login", method = RequestMethod.GET)
    @CrossOrigin(origins = {"*"})
    public ResponseEntity<?> login(
            @RequestParam(value="email", required=false, defaultValue="email") String email,
            @RequestParam(value="password", required=false, defaultValue="password") String password, 
            HttpServletRequest request
            ) throws  Exception {
            List<Account> acc = accountRepository.findByEmail(email);

            HttpSession session = request.getSession(true);
            session.setAttribute("user", acc);

            System.out.println("logged>>>"+acc);
            System.out.println("session>>>"+session);

            return new ResponseEntity<>(acc, HttpStatus.OK);
    }

    @SuppressWarnings("unchecked")
    @RequestMapping(value = "/logout", method = RequestMethod.GET)
    @CrossOrigin(origins = {"*"})
    public ResponseEntity<?> logout(
            HttpServletRequest request
            ) throws  Exception {

            HttpSession session = request.getSession(true);
            List<Account> acc = (List<Account>) session.getAttribute("user");

            session.removeAttribute("user");            

            System.out.println("logout>>>"+acc);
            System.out.println("session>>>"+session);

            return new ResponseEntity<>(acc, HttpStatus.OK);
    }

    @RequestMapping(value = "/forgot", method = RequestMethod.GET)
    @CrossOrigin(origins = {"*"})
    public ResponseEntity<?> forgot(
            @RequestParam(value="email", required=false, defaultValue="email") String email
            ) throws  Exception {
            List<Account> acc = accountRepository.findByEmail(email);
            return new ResponseEntity<>(acc, HttpStatus.OK);
    }

    @RequestMapping(value = "/edit", method = RequestMethod.GET)
    @CrossOrigin(origins = {"*"})
    public ResponseEntity<?> edit(
            @RequestParam(value="username", required=false, defaultValue="username") String username,
            @RequestParam(value="password", required=false, defaultValue="password") String password,
            @RequestParam(value="email", required=false, defaultValue="email") String email
            ) throws  Exception {
            Account acc = accountRepository.findByUsername(username);
            return new ResponseEntity<>(acc, HttpStatus.OK);
    }

    @RequestMapping(value = "/register", method = RequestMethod.GET)
    @CrossOrigin(origins = {"*"})
    public ResponseEntity<?> register(
            @RequestParam(value="username", required=false, defaultValue="username") String username,
            @RequestParam(value="password", required=false, defaultValue="password") String password,
            @RequestParam(value="email", required=false, defaultValue="email") String email
            ) throws  Exception {
        Account checkAccount = accountRepository.findByUsername(username);
        System.out.println("checkAccount>>>"+checkAccount);
        if (checkAccount == null) {
            try {               
                // if not create some
                Account newAcc = accountRepository.saveAndFlush(new Account(
                            username, 
                            password, 
                            email
                        ));
                System.out.println("newAcc>>>"+checkAccount);
                return new ResponseEntity<>(newAcc, HttpStatus.OK);
            }
            catch (Exception e) {
                e.printStackTrace();
                System.out.println("error adding user>>>"+checkAccount);
                return new ResponseEntity<>(e, HttpStatus.OK);
            }
        }else{
            // String e = "user exists";
            System.out.println("user already exists>>>"+checkAccount);
            return new ResponseEntity<>(checkAccount, HttpStatus.OK);
        }
    }   

}

这是final Random r = new SecureRandom(); byte[] SALT = new byte[20]; r.nextBytes(SALT); lkey = "MyGooglePlayKey(hidden)"; android_id = Settings.Secure.getString(getApplicationContext().getContentResolver(), Settings.Secure.ANDROID_ID); mLicenseCheckerCallback = new MyLicenseCheckerCallback(); mChecker = new LicenseChecker( this, new ServerManagedPolicy(this, new AESObfuscator(SALT, getPackageName(), android_id)), lkey); 的问题吗?当然,许可Android文档根本不提供有关如何获取设备ID的帮助,并且使用不同的方法需要另一个权限。我的方法导致Android Studio说“不建议使用getString获取设备标识符”。

由于旧的Lollipop错误,我的LicenseChecker类必须更改为使用明确的意图:

Settings.Secure.getString(getApplicationContext().getContentResolver(), Settings.Secure.ANDROID_ID)

我的LVL库使用与我的app相同的targetSDK / compile / minSDK:

if (mService == null) {
            Log.i(TAG, "Binding to licensing service.");
            try {
                Intent serviceIntent = new Intent(new String(Base64.decode("Y29tLmFuZHJvaWQudmVuZGluZy5saWNlbnNpbmcuSUxpY2Vuc2luZ1NlcnZpY2U=")))
                        .setPackage("com.android.vending");

                boolean bindResult = mContext.bindService(serviceIntent,
                        this, // ServiceConnection.
                        Context.BIND_AUTO_CREATE);

由于不推荐android { compileSdkVersion 26 buildToolsVersion "26.0.1" useLibrary 'org.apache.http.legacy' defaultConfig { minSdkVersion 17 targetSdkVersion 26 } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt' } } dependencies { compile group: 'org.apache.httpcomponents' , name: 'httpclient-android' , version: '4.3.5.1' } NamePairValue方法,我不得不使用这些Apache替代品。

1 个答案:

答案 0 :(得分:0)

我不是这方面的专家,但我认为盐只是随机的,因为它对你的应用来说是随机的。您不会动态生成它。请参阅documentation

  

要使用AESObfuscator,请先将其导入您的Activity。声明一个私有静态final数组来保存salt字节并将其初始化为20个随机生成的字节。

...
// Generate 20 random bytes, and put them here.
private static final byte[] SALT = new byte[] {
 -46, 65, 30, -128, -103, -57, 74, -64, 51, 88, -95,
 -45, 77, -117, -36, -113, -11, 32, -64, 89
 };
...