我正在为我的JEE6应用程序编写授权过滤器,以便能够限制对某些页面的某些用户的访问。由于某种原因,浏览器根本不显示任何页面(我只看到白色)。某处有一个bug,但我不知道在哪里,我是JEE6安全新手,我正在尝试以最简单的方式实现我的身份验证机制。
这是我的源代码
过滤器:
public class RestrictPageFilter implements Filter {
private FilterConfig fc;
private InputStream in;
private Access access;
public void init(FilterConfig filterConfig) throws ServletException {
// The easiest way to initialize the filter
fc = filterConfig;
// Prepare the parsing
try {
in = Thread.currentThread().getContextClassLoader()
.getResourceAsStream("allowedpages.xml");
Access access = (Access) JAXBContext.newInstance(Access.class)
.createUnmarshaller().unmarshal(in);
} catch (JAXBException e) {
e.printStackTrace();
}
}
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse resp = (HttpServletResponse) response;
HttpSession session = req.getSession(true);
String pageRequested = req.getRequestURL().toString();
// Get the value of the current logged user
Role currentUser = (Role) session.getAttribute("userRole");
if (currentUser != null) {
if (currentUser.getType().equals("BUYER")) {
List<String> buyerPages = access.getBuyer().getPages();
for (String s : buyerPages) {
if (pageRequested.contains(s)) {
chain.doFilter(request, response);
} else {
resp.sendRedirect("main.xml");
}
}
} else if (currentUser.getType().equals("SELLER")) {
List<String> buyerPages = access.getSeller().getPages();
for (String s : buyerPages) {
if (pageRequested.contains(s)) {
chain.doFilter(request, response);
} else {
resp.sendRedirect("main.xml");
}
}
} else if (currentUser.getType().equals("ADMINISTRATOR")) {
List<String> buyerPages = access.getAdministrator().getPages();
for (String s : buyerPages) {
if (pageRequested.contains(s)) {
chain.doFilter(request, response);
} else {
resp.sendRedirect("main.xml");
}
}
}
}
}
public void destroy() {
// Not needed
}
}
为了支持这个过滤器,我使用一个.xml文件(位于WEB-INF / classes中),该文件包含允许的页面以及一个bean,用于存储.xml的详细信息作为对象:
<access>
<buyer>
<page>buyoffer.xhtml</page>
<page>faq.xhtml</page>
<page>index.jsp</page>
<page>login.xhtml</page>
<page>main.xhtml</page>
<page>registrationSucceded.xhtml</page>
</buyer>
<seller>
<page>sellerpanel.xhtml</page>
<page>faq.xhtml</page>
<page>index.jsp</page>
<page>login.xhtml</page>
<page>main.xhtml</page>
<page>registrationSucceded.xhtml</page>
</seller>
<administrator>
<page>sellerpanel.xhtml</page>
<page>faq.xhtml</page>
<page>index.jsp</page>
<page>login.xhtml</page>
<page>main.xhtml</page>
<page>registrationSucceded.xhtml</page>
</administrator>
</access>
-
package simplebeans;
import java.util.List;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement
public class Access {
@XmlElement
private User buyer;
@XmlElement
private User seller;
@XmlElement
private User administrator;
public User getBuyer() {
return buyer;
}
public User getSeller() {
return seller;
}
public User getAdministrator() {
return administrator;
}
@XmlRootElement
public static class User {
@XmlElement(name="page")
private List<String> pages;
public List<String> getPages() {
return pages;
}
}
}
这是我将过滤器添加到web.xml文件的方式:
<!--Page restriction filter -->
<filter>
<filter-name>restrict</filter-name>
<filter-class>filters.RestrictPageFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>restrict</filter-name>
<url-pattern>*.xhtml</url-pattern>
</filter-mapping>
您认为我在浏览器中只看到白色的原因是什么? 我尝试使用URL导航到某些页面,但我只看到白色。
更新的 我做了一些更改,以便能够允许未登录的用户看到一些页面,但我得到了一个NPE:
doFilter方法的更改:
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse resp = (HttpServletResponse) response;
HttpSession session = req.getSession(true);
String pageRequested = req.getRequestURL().toString();
// Get the value of the current logged user
Role currentUser = (Role) session.getAttribute("userRole");
boolean authorized = false;
if (!pageRequested.contains("main.xhtml") && currentUser != null) {
switch (currentUser.getType()) {
case BUYER:
for (String s : access.getBuyer().getPages()) {
if (pageRequested.contains(s)) {
authorized = true;
}
}
break;
case SELLER:
for (String s : access.getSeller().getPages()) {
if (pageRequested.contains(s)) {
authorized = true;
}
}
break;
case ADMINISTRATOR:
for (String s : access.getAdministrator().getPages()) {
if (pageRequested.contains(s)) {
authorized = true;
}
}
break;
}
}
else {
for (String s : access.getVisitor().getPages()) {
if (pageRequested.contains(s)) {
authorized = true;
}
}
}
if (authorized || pageRequested.contains("main.xhtml")) {
chain.doFilter(request, response);
} else {
resp.sendRedirect("main.xhtml");
}
}
xml文件的更改:
<visitor>
<page>faq.xhtml</page>
<page>login.xhtml</page>
<page>main.xhtml</page>
<page>registration.xhtml</page>
<page>registrationbuyer.xhtml</page>
<page>registrationseller.xhtml</page>
</visitor>
对Access bean所做的更改:
@XmlElement
private User visitor;
public User getVisitor() {
return visitor;
}
答案 0 :(得分:3)
如果您没有看到任何内容,则过滤器已阻止该请求。即它既没有继续链,也没有转发或重定向请求。你的代码流是不合逻辑的。当前用户为null
或当前用户没有任何这些角色时,您也应该进行重定向。您还应该在整个过滤器代码中有效地呼叫chain.doFilter()
或response.sendRedirect()
一次。现在你在循环中为每个页面多次调用它们。那些方法调用不会神奇地中止for
循环。
我建议重写主if
块,如下所示
boolean authorized = false;
if (currentUser != null) {
if (currentUser.getType().equals("BUYER")) {
for (String s : access.getBuyer().getPages()) {
if (pageRequested.contains(s)) {
authorized = true;
break;
}
}
} else if (currentUser.getType().equals("SELLER")) {
for (String s : access.getSeller().getPages()) {
if (pageRequested.contains(s)) {
authorized = true;
break;
}
}
} else if (currentUser.getType().equals("ADMINISTRATOR")) {
for (String s : access.getAdministrator().getPages()) {
if (pageRequested.contains(s)) {
authorized = true;
break;
}
}
}
}
if (authorized) {
chain.doFilter(request, response);
} else {
resp.sendRedirect("main.xhtml");
}
我个人也将CurrentUser#getType()
设为enum
,以便您可以使用switch
代替if else if else if else ...
并将三个重复的块重构为单个辅助方法
更新:根据您的重定向循环问题,如果您的过滤器映射到/*
之类的通用网址格式(也涵盖main.xhtml
而不是例如/secured/*
,那么当当前请求的页面为main.xhtml
时,您需要不重定向请求,但您需要继续链接。您可以通过在当前请求的页面为if
时跳过主main.xhtml
检查来执行此操作。无论如何,您都不关心main.xhtml
的授权。