You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android应用连接MS SQL数据库失败求解决方案(附代码)

Android连接MS SQL Server实现登录功能的问题修复方案

一、代码中的关键错误

  • 驱动类名拼写错误:原代码中net.sourceforge.jtds.jtbc.Driver是错误的,正确的JTDS驱动类名是net.sourceforge.jtds.jdbc.Driver
  • SQL注入风险:直接拼接用户输入的账号到SQL语句中,极易引发SQL注入,必须使用参数绑定
  • 无用的StrictMode配置:已经使用AsyncTask在后台线程处理数据库操作,无需开启StrictMode.permitAll(),这会破坏Android线程规范
  • 缺失核心连接类实现:代码中调用的ConnectionHelper未提供实现,这是连接失败的核心原因之一

二、必要的前置配置

  1. 添加网络权限:在AndroidManifest.xml中添加互联网权限:
<uses-permission android:name="android.permission.INTERNET"/>
  1. 添加JTDS依赖:在app/build.gradle的dependencies中添加JTDS驱动:
implementation 'net.sourceforge.jtds:jtds:1.3.1'
  1. SQL Server端配置:
    • 开启SQL Server远程连接(在SQL Server配置管理器中启用TCP/IP协议并设置端口)
    • 开放对应端口的防火墙权限(默认1433,自定义端口需对应开放)
    • 启用SQL Server混合身份验证模式,确保数据库账号具备远程访问权限

三、修正后的完整代码

1. ConnectionHelper连接类实现

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;

public class ConnectionHelper {
    // 替换为你的数据库实际配置
    private static final String IP = "你的数据库IP";
    private static final String PORT = "你的数据库端口";
    private static final String DATABASE_NAME = "你的数据库名";
    private static final String DB_USERNAME = "数据库登录账号";
    private static final String DB_PASSWORD = "数据库登录密码";
    private static final String CONNECTION_URL = "jdbc:jtds:sqlserver://" + IP + ":" + PORT + "/" + DATABASE_NAME;

    public static Connection CONN() {
        Connection conn = null;
        try {
            Class.forName("net.sourceforge.jtds.jdbc.Driver");
            conn = DriverManager.getConnection(CONNECTION_URL, DB_USERNAME, DB_PASSWORD);
        } catch (ClassNotFoundException | SQLException e) {
            e.printStackTrace();
        }
        return conn;
    }
}

2. 修正后的LoginActivity

import android.content.Intent;
import android.content.SharedPreferences;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import androidx.appcompat.app.AppCompatActivity;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

public class LoginActivity extends AppCompatActivity {

    private EditText userNameET, passwordEt;
    private Button loginBTN;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_login);

        userNameET = findViewById(R.id.userNameEditText);
        passwordEt = findViewById(R.id.passEditText);
        loginBTN = findViewById(R.id.loginBtn);
    }

    private class DoLoginForUser extends AsyncTask<Void, Void, String> {
        private final String userId;
        private final String userPassword;

        public DoLoginForUser(String userId, String userPassword) {
            this.userId = userId;
            this.userPassword = userPassword;
        }

        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            loginBTN.setVisibility(View.GONE);
        }

        @Override
        protected String doInBackground(Void... voids) {
            Connection connect = null;
            PreparedStatement ps = null;
            ResultSet rs = null;

            try {
                connect = ConnectionHelper.CONN();
                if (connect == null) {
                    return "无法连接到数据库";
                }

                // 使用参数绑定避免SQL注入
                String query = "SELECT password FROM testDatabase WHERE UserId = ?";
                ps = connect.prepareStatement(query);
                ps.setString(1, userId);

                Log.e("query", query);
                rs = ps.executeQuery();

                if (rs.next()) {
                    String storedPassword = rs.getString("password");
                    if (storedPassword != null && storedPassword.trim().equals(userPassword)) {
                        return "success";
                    } else {
                        return "无效的凭据";
                    }
                } else {
                    return "用户不存在";
                }
            } catch (SQLException e) {
                return "错误: " + e.getMessage();
            } finally {
                // 确保资源全部关闭
                try {
                    if (rs != null) rs.close();
                    if (ps != null) ps.close();
                    if (connect != null) connect.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }

        @Override
        protected void onPostExecute(String result) {
            super.onPostExecute(result);
            loginBTN.setVisibility(View.VISIBLE);

            if ("success".equals(result)) {
                SharedPreferences sharedPreferences = getApplicationContext().getSharedPreferences("userdetails", 0);
                SharedPreferences.Editor editor = sharedPreferences.edit();
                editor.putString("email", userNameET.getText().toString());
                editor.apply(); // 异步提交更高效

                Intent i = new Intent(LoginActivity.this, MainActivity.class);
                startActivity(i);
                finish(); // 结束登录页,避免返回
            } else {
                // 可添加Toast/Snackbar提示错误信息
                // Toast.makeText(LoginActivity.this, result, Toast.LENGTH_SHORT).show();
            }
        }
    }

    public void DoLogin(View v) {
        String userId = userNameET.getText().toString().trim();
        String password = passwordEt.getText().toString().trim();

        // 本地输入校验
        if (userId.isEmpty() || password.isEmpty()) {
            // Toast.makeText(this, "请输入用户名和密码", Toast.LENGTH_SHORT).show();
            return;
        }

        new DoLoginForUser(userId, password).execute();
    }
}

四、额外最佳实践

  • 敏感信息存储:数据库IP、账号等敏感信息不要硬编码,可放在strings.xml或使用Android安全存储方案
  • 密码安全:数据库中不要存储明文密码,应存储加盐后的哈希值(如SHA-256),登录时对比哈希值
  • 异步任务替代:AsyncTask已被弃用,推荐使用Coroutines或WorkManager处理后台任务
  • 错误提示优化:在onPostExecute中添加明确的错误提示,帮助定位问题

内容的提问来源于stack exchange,提问作者Jesse Tee

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.03 11:01:34