我应该如何将我的用户名和密码发送到Java后端?

时间:2017-02-06 06:56:12

标签: java mysql jersey jax-rs

目前我正在使用此方法向我的后端发送用户名和密码,并检查数据库中是否有效。 代码在这里:

@GET
@Path("/login/{username}/{passWord}")
public Boolean Login(@PathParam("username") String username, @PathParam("passWord") String password) {
    LoginService login = new LoginService();
    boolean response = login.LoginCheck(username, password);
    return response;
}

在LoginService中我使用此方法来验证::

public class LoginService {
    private int count;      
    public LoginService() {}                
    public boolean LoginCheck(String uname, String password) {
        SessionFactory factory = new Configuration().configure().buildSessionFactory();
        Session session = SessionUtil.getSession();
        String hql = "select reg.name,reg.password from Employee as reg where reg.name='" + uname + "' and reg.password='" + password + "'";
        Query query = session.createQuery(hql);
        for (Iterator it = query.iterate(); it.hasNext();) {            
            it.next();
            count++;
        }
        System.out.println("Total rows: " + count);
        if (count == 1) {
            return true;
        } else {
            return false;
        }
    }       
}

我想知道有没有其他最安全的方式来发送用户名和密码?在这里,用户名和密码反映在URL中。

先谢谢。

2 个答案:

答案 0 :(得分:1)

您应该考虑使用 Basic Auth RFC 2617)。实现它的Servlet过滤器可能如下所示:

package transfer.util;

import static org.apache.commons.lang3.StringUtils.*;

import java.io.IOException;
import java.security.Principal;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import javax.ws.rs.core.HttpHeaders;

import org.omnifaces.filter.HttpFilter;

import transfer.business.users.entity.Roles;

@WebFilter("/api/*")
public class BasicAuthFilter extends HttpFilter {

    @Override
    public void doFilter(final HttpServletRequest request, final HttpServletResponse response, final HttpSession session, final FilterChain chain) throws ServletException, IOException {

        // insert cookie erasure here if needed

        dontCache(response);

        final String authHeader = request.getHeader(HttpHeaders.AUTHORIZATION);

        if (isNotBlank(authHeader)) {
            if (isValid(authHeader)) {
                chain.doFilter(wrapRequest(request, new SimplePrincipal(webHookUser, Roles.ISSUETRACKER)), response);
            } else {
                sendAuthError(response);
            }
        } else {
            sendAuthError(response);
        }
    }

    private void dontCache(final HttpServletResponse response) {
        response.setHeader("Cache-Control", "no-cache, no-store, must-revalidate");
        response.setHeader("Pragma", "no-cache");
        response.setDateHeader("Expires", 0);
    }

    private boolean isValid(final String authHeader) {
        // check credentials and return true or false
    }

    private HttpServletRequest wrapRequest(final HttpServletRequest request, final SimplePrincipal principal) {
        final HttpServletRequestWrapper wrapper = new HttpServletRequestWrapper(request) {
            @Override
            public Principal getUserPrincipal() {
                return principal;
            }

            @Override
            public String getRemoteUser() {
                return principal.getName();
            }

            @Override
            public boolean isUserInRole(final String role) {
                return principal.getRoles().contains(role);
            }
        };
        return wrapper;
    }

    private void sendAuthError(final HttpServletResponse response) throws IOException {

        response.setHeader("WWW-Authenticate", "Basic realm=\"default\"");
        response.sendError(HttpServletResponse.SC_UNAUTHORIZED);
    }
}

此示例使用OmniFacesApache Commons Lang。它不显示用户凭据的具体验证查询。请参阅参数化SQL查询上的Giovanni Lovatos answer。正如他所提到的,这只是通过HTTPS安全,它通过证书添加传输加密和服务器身份验证以及可选的客户端身份验证。 HTTPS / TLS的配置因Java应用程序服务器实现而异。

答案 1 :(得分:0)

向您的后端发送用户名和密码数据的更安全的方法可能是POST请求,这会阻止在请求网址中同时包含这两个字段:

@POST
@Path("/login")
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
public boolean login(@FormParam("username") String username,
                     @FormParam("password") String password) {
    LoginService login = new LoginService();
    boolean response = login.LoginCheck(username, password);
    return response;
}

然后,如果您使用HTML表单登录,您将拥有以下内容:

<form method="post" action="/login">
    <input type="text" name="username">
    <input type="password" name="password">
</form>

请注意,POST请求仍然在其正文中以明文形式显示密码,因此安全性必须使服务在TLS中运行(即通过HTTPS)。

至少但不是最后,你绝对应该避免使用字符串连接来构建SQL查询,尤其是涉及密码时,因为这可能会导致 SQL注入 [1]。您应该使用预处理语句和参数,这对于Hibernate非常简单:

String hql = "select reg.name, reg.password from Employee as reg where reg.name = ? and reg.password = ?";
Query query = session.createQuery(hql);
query.setParameter(1, uname);
query.setParameter(2, password);
  1. https://en.wikipedia.org/wiki/SQL_injection