Java EE 中的访问控制
Posted
技术标签:
【中文标题】Java EE 中的访问控制【英文标题】:Access Control in Java EE 【发布时间】:2014-06-20 14:56:57 【问题描述】:我正在开发一个简单的 Java EE 应用程序,使用纯 jsp servets 以及 POJO
类和 DAO
支持。在这里实现访问控制的最佳策略是什么。
我最初想使用filter
,但我不太确定它的用法,那么有什么简单的编程方式可以实现吗?我的意思是通过使用properties
文件或其他方法?
我还想保持我的应用程序重量轻。所以请提出相同的解决方案?提前致谢!
【问题讨论】:
【参考方案1】:基本上,ACL 是在 Java EE 中通过在会话 bean 类或其方法上使用 @DeclareRoles 和 @RolesAllowed 注释来实现的,以实现编程安全性。您还可以在部署描述符 (web.xml) 中使用元素来描述您的角色和授权以实现 decalrative 安全性。
这是来自Java EE tutorial 的程序安全示例
package converter.ejb;
import java.math.BigDecimal;
import javax.ejb.Stateless;
import java.security.Principal;
import javax.annotation.Resource;
import javax.ejb.SessionContext;
import javax.annotation.security.DeclareRoles;
import javax.annotation.security.RolesAllowed;
@Stateless()
@DeclareRoles("TutorialUser")
public class ConverterBean
@Resource SessionContext ctx;
private BigDecimal yenRate = new BigDecimal("89.5094");
private BigDecimal euroRate = new BigDecimal("0.0081");
@RolesAllowed("TutorialUser")
public BigDecimal dollarToYen(BigDecimal dollars)
BigDecimal result = new BigDecimal("0.0");
Principal callerPrincipal = ctx.getCallerPrincipal();
if (ctx.isCallerInRole("TutorialUser"))
result = dollars.multiply(yenRate);
return result.setScale(2, BigDecimal.ROUND_UP);
else
return result.setScale(2, BigDecimal.ROUND_UP);
@RolesAllowed("TutorialUser")
public BigDecimal yenToEuro(BigDecimal yen)
BigDecimal result = new BigDecimal("0.0");
Principal callerPrincipal = ctx.getCallerPrincipal();
if (ctx.isCallerInRole("TutorialUser"))
result = yen.multiply(euroRate);
return result.setScale(2, BigDecimal.ROUND_UP);
else
return result.setScale(2, BigDecimal.ROUND_UP);
您也可以在您的 servlet 中使用 HttpServletRequest 的登录、注销和身份验证方法进行身份验证,然后使用 getUserPrincipal 和 isUserInRole 进行 ACL。然后,您需要添加到 web.xml 中的 servlet 描述,以引用在 web.xml 中的元素中声明的角色。这是来自Java EE turorial 的 ACL 部分示例。
package enterprise.programmatic_login;
import java.io.*;
import java.net.*;
import javax.annotation.security.DeclareRoles;
import javax.servlet.*;
import javax.servlet.http.*;
@DeclareRoles("javaee6user")
public class LoginServlet extends HttpServlet
/**
* Processes requests for both HTTP GET and POST methods.
* @param request servlet request
* @param response servlet response
*/
protected void processRequest(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException
response.setContentType("text/html;charset=UTF-8");
PrintWriter out = response.getWriter();
try
String userName = request.getParameter("txtUserName");
String password = request.getParameter("txtPassword");
out.println("Before Login" + "<br><br>");
out.println("IsUserInRole?.."
+ request.isUserInRole("javaee6user")+"<br>");
out.println("getRemoteUser?.." + request.getRemoteUser()+"<br>");
out.println("getUserPrincipal?.."
+ request.getUserPrincipal()+"<br>");
out.println("getAuthType?.." + request.getAuthType()+"<br><br>");
try
request.login(userName, password);
catch(ServletException ex)
out.println("Login Failed with a ServletException.."
+ ex.getMessage());
return;
out.println("After Login..."+"<br><br>");
out.println("IsUserInRole?.."
+ request.isUserInRole("javaee6user")+"<br>");
out.println("getRemoteUser?.." + request.getRemoteUser()+"<br>");
out.println("getUserPrincipal?.."
+ request.getUserPrincipal()+"<br>");
out.println("getAuthType?.." + request.getAuthType()+"<br><br>");
request.logout();
out.println("After Logout..."+"<br><br>");
out.println("IsUserInRole?.."
+ request.isUserInRole("javaee6user")+"<br>");
out.println("getRemoteUser?.." + request.getRemoteUser()+"<br>");
out.println("getUserPrincipal?.."
+ request.getUserPrincipal()+"<br>");
out.println("getAuthType?.." + request.getAuthType()+"<br>");
finally
out.close();
查看提供的 Java EE 教程链接以获得更完整的示例和说明。
【讨论】:
【参考方案2】:如果您不打算使用某些 API(如 spring security 或 apache shiro),您将需要网络过滤器。
在您的过滤器实现中,如果您想授予访问权限,只需调用
chain.doFilter(request, response);
它将正常处理请求,否则将用户重定向到另一个页面使用
response.sendRedirect(Url);
是个不错的选择
【讨论】:
以上是关于Java EE 中的访问控制的主要内容,如果未能解决你的问题,请参考以下文章