2013-02-19 217 views
5

经过大量的关于stackoverflow的研究后,我张贴这个问题,因为我找不到解决方案的问题。Struts2的URL标记 - 隐藏查询字符串

要求方案:根据每个客户ID作为参数更新客户列表。

解决方案尝试:基于从jsp接收到的客户ID,将它作为Struts2 url标记传递给Action。

面临的问题 - 在URL上可见的查询字符串。
http://foo.com/Struts2Example/getCustomerAction?customerId=2

问题:

  1. 难道我们不能隐藏查询字符串,如果我们使用Struts网址标记?
  2. 如果我们在使用Url标签时无法隐藏使用的查询字符串?上述场景的替代方案是什么?

代码struts.xml中,JSP和下面的动作 -

<h2>All Customers Details</h2> 

<s:if test="customerList.size() > 0"> 
    <table border="1px" cellpadding="8px"> 
     <tr> 
      <th>Customer Id</th> 
      <th>First Name</th> 
      <th>Last Name</th> 
      <th>Age</th> 
      <th>Created Date</th> 
     </tr> 
     <s:iterator value="customerList" status="userStatus"> 
      <tr> 
       <td><s:url var="editCustomer" action="getCustomerAction"> 
         <s:param name="customerId" value="%{customerId}" /> 
        </s:url> 

        <p> 
         <s:a href="%{editCustomer}"> 
          <s:property value="customerId" /> 
         </s:a> 
        </p></td> 

       <td><s:property value="firstname" /></td> 
       <td><s:property value="lastname" /></td> 
       <td><s:property value="age" /></td> 
       <td><s:date name="createdDate" format="dd/MM/yyyy" /></td> 
      </tr> 
     </s:iterator> 
    </table> 
</s:if> 
<br /> 
<br /> 

struts.xml-

<!-- Get Customer Details - To Pre-Populate the form to update a Customer --> 
    <action name="getCustomerAction" method="getCustomerById" 
     class="com.hcl.customer.action.CustomerAction"> 
     <result name="success">pages/customerForm.jsp </result> 
    </action> 

客户采取的行动接收机类

public class CustomerAction extends ActionSupport implements ModelDriven { 

Logger logger = Logger.getLogger(CustomerAction.class); 

Customer customer = new Customer(); 

List<Customer> customerList = new ArrayList<Customer>(); 
CustomerDAO customerDAO = new CustomerDAOImpl(); 

public Customer getCustomer() { 
    return customer; 
} 

//Set Customer onto Value Stack 
public void setCustomer(Customer customer) { 
    this.customer = customer; 
} 

public List<Customer> getCustomerList() { 
    return customerList; 
} 

//Set Customer List onto Value Stack 
public void setCustomerList(List<Customer> customerList) { 
    this.customerList = customerList; 
} 

public String execute() throws Exception { 
    return SUCCESS; 
} 

public Object getModel() { 
    return customer; 
} 



// Edit customer details, it will retrieve the records based on customerId 
//SkipValidation is used to skip the validate() 
@SkipValidation 
public String getCustomerById() { 

    logger.info("** Customer Id to edit ** " + customer.getCustomerId()); 

    customer = customerDAO.customerById(customer.getCustomerId()); 

    return SUCCESS; 

} 
+0

为什么你想隐藏ID?如果您将值存储在客户端,任何人都可以查看源代码并获取它。您当然可以使用帖子发送结果,但考虑用户需要为页面添加书签。真的,答案是安全性......该用户是否应该能够访问该客户ID?如果不是,那么在任何情况下都不应该被允许。 – Quaternion 2013-02-19 05:41:31

+0

是的,用户可以像这样收藏一个页面......但问题是,当URL为'** getCustomer ** Action?customerId = 2'时,更新客户'...这里有点奇怪:> – 2013-02-19 09:06:33

+0

@AndreaLigios - 情景是,为了更新客户,我必须在表单上预先填写他的详细信息。要获取细节,我使用customerId查询数据库。 – 2013-02-19 10:48:13

回答

1

一些无序因素仍然这样做的用户ID查找:

  • 使用不同的操作(execute方法只) ,或同一动作的不同方法来执行不同的“动作”;
  • 每个动作的名称/方法应该匹配操作中执行和不言自明,例如,你应该有一个editCustomer方法(或动作),以编辑客户和一个getCustomer方法(或动作),以获得客户;
  • GET HTTP方法应该用于读取数据,而POST HTTP方法应该用于发送数据;每个非读操作理应通过POST执行;使用GET发送数据是20年前出现的一种古老的不良习惯,从未死亡:/使用POST的原因是隐藏的URL,更高的负载能力,发送二进制数据的能力等等。

也就是说,像http://foo.com/Struts2Example/getCustomerAction?customerId=2的网址应清晰可见(被书签为例),理想的应该美化(REST风格,像StackOverflow的):像http://foo.com/Struts2Example/Customer/2/

的URL像http://foo.com/Struts2Example/editCustomerAction?customerId=2可以”因为你没有传递任何其他参数;你知道要编辑的客户的ID,但不是要更改的数据... 它会变成类似于: http://foo.com/Struts2Example/editCustomerAction?customerId=2&name=foo&lastname=bar&age=42,这将工作,但正如说(和作为你的问题问)应该隐藏,并处理通过POST。

如果您要在页面的source中打印ID,那么应该不需要将它们隐藏给用户;

您需要做的是确保用户不能在指定的范围之外更改ID; 如果您在页面中绘制了ID {1,2,3}的客户列表,您必须阻止用户尝试更改标识并试图用ID = 4更新客户...以实现此目的,只需将ID列表存储在session之前填充页面,然后检查页面返回的ID对列表。如果它们不匹配,则阻止恶意操作。

希望有帮助

+0

感谢您的时间和答复。完全同意你的意见,w.r.t行动/方法名称。其次,由于我没有在这里使用表格,我如何在POST中提出请求作为POST?感谢您的帮助。 – 2013-02-19 11:16:25

+0

不客气,你为什么不使用表格?为什么你不能添加一个?他们是免费的:) – 2013-02-19 11:31:04

+0

虽然情况并不需要一个表格。由于我没有找到任何其他选择适合我不如去与表单。此外,因为他们是免费的;)谢谢大家对我的疑问的回应。欣赏它!干杯! – 2013-02-20 14:11:11

1

一种替代,是加密userID并将其发送回HTML页面。维护客户端的映射。当您提交请求时,POST POST加密值。解密/加密逻辑将在服务器端。 这会增加系统的开销,但与安全性相比,这对性能有足够的权衡。 也请看看@ jcryption.org/info,它在MIT和GPL许可下。

更简单的解决方案是将其转换为“POST”操作,以便值在HTTP请求正文内传递。如果它通过HTTPS,它会被加密,但是你可以使用谷歌开发者工具或IE9开发模式

+0

将注释转换为答案。请忽略评论。谢谢 – user1428716 2013-02-19 04:21:01

+0

@ user1428716-感谢您的回答。在这种情况下,因为即时通讯不使用struts表单,我如何实现/转换请求到POST? – 2013-02-19 11:18:26