- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
(2013 年 1 月 2 日更新)我现在已将所有代码和 pom.xml 添加到 github https://github.com/AndyWi/GuiceJerseyJettyShiroExample(结束更新)
我正在尝试使用 Shiro 将基于表单的身份验证添加到我的简单应用程序中。该应用程序使用 Guice 3.0、Jersey 1.16 和 Shiro 1.2.1,运行在嵌入式 Jetty 9.0.0.M4 上。
我的问题是(据我所知)Shiro 需要通过 Guice 提供 login.jsp,然后添加到 Shiro 的过滤器链中。但是,当我这样做时,Jetty 找不到 login.jsp。当我从 Guice 过滤器中排除 login.jsp 时,Jetty 可以找到该 jsp,但它对 Shiro 不可用,因此身份验证不起作用。
因此,在我的 Bootstrap 代码中,我使用这一行将 login.jsp 添加到 Guice 过滤器:
webAppContext.addFilter(GuiceFilter.class, "/login.jsp", null);
在我的 ShiroWebModule 中,我像这样添加 login.jsp:
addFilterChain("/login.jsp", AUTHC);
我花了非常长的时间来寻找这个问题的答案,却没有任何迹象表明其他人也遇到过同样的问题——这意味着我显然做了一些非常简单的错误!但我不知道它是什么。如果有人能帮助我解决这个问题,我将不胜感激。
我已将我的项目精简为一个小示例来演示问题。所有这一切应该做的是接受/api/uuid 的 rest url,将用户重定向到 login.jsp,接受任何用户名/密码组合进行身份验证,然后从/api/uuid 服务返回一个新的 UUID;用户还应保持登录状态以备将来请求。这是完整的代码,希望它能帮助那里的人发现问题:
Bootstrap :
package eg.guicejerseyjettyshiro;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.servlet.DefaultServlet;
import org.eclipse.jetty.webapp.WebAppContext;
import com.google.inject.servlet.GuiceFilter;
import eg.guicejerseyjettyshiro.modules.EgGuiceServletContextListener;
public class Bootstrap {
public static void main(String[] args) throws Exception {
Server server = new Server(8081);
WebAppContext webAppContext = new WebAppContext();
webAppContext.setContextPath("/");
webAppContext.setResourceBase("src/main/webapp/");
webAppContext.setParentLoaderPriority(true);
webAppContext.addEventListener(new EgGuiceServletContextListener());
webAppContext.addFilter(GuiceFilter.class, "/api/*", null);
// **** Shiro needs login.jsp to go through the GuiceFilter,
// but Jetty can't find the jsp when this happens. Commenting
// out this line lets Jetty find the jsp, but Shiro can't see it:
webAppContext.addFilter(GuiceFilter.class, "/login.jsp", null);
webAppContext.addServlet(DefaultServlet.class, "/");
server.setHandler(webAppContext);
server.start();
server.join();
}
}
EgGuiceServletContextListener:
package eg.guicejerseyjettyshiro.modules;
import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.servlet.GuiceServletContextListener;
public class EgGuiceServletContextListener extends GuiceServletContextListener {
private ServletContext servletContext;
@Override
public void contextInitialized(ServletContextEvent servletContextEvent) {
this.servletContext = servletContextEvent.getServletContext();
super.contextInitialized(servletContextEvent);
}
@Override
protected Injector getInjector() {
return Guice.createInjector(
new EgJerseyServletModule(),
new EgShiroWebModule(this.servletContext));
}
}
EgJerseyServletModule:
package eg.guicejerseyjettyshiro.modules;
import org.apache.shiro.guice.web.GuiceShiroFilter;
import com.sun.jersey.guice.JerseyServletModule;
import com.sun.jersey.guice.spi.container.servlet.GuiceContainer;
import eg.guicejerseyjettyshiro.dao.UuidDao;
import eg.guicejerseyjettyshiro.services.UuidService;
public class EgJerseyServletModule extends JerseyServletModule {
@Override
protected void configureServlets() {
bindings();
filters();
}
private void bindings() {
bind(UuidDao.class);
bind(UuidService.class);
}
private void filters() {
filter("/*").through(GuiceShiroFilter.class);
filter("/*").through(GuiceContainer.class);
}
}
EgShiroWebModule:
package eg.guicejerseyjettyshiro.modules;
import javax.servlet.ServletContext;
import org.apache.shiro.guice.web.ShiroWebModule;
import com.google.inject.name.Names;
import eg.guicejerseyjettyshiro.realms.EgAuthorizingRealm;
public class EgShiroWebModule extends ShiroWebModule {
public EgShiroWebModule(ServletContext servletContext) {
super(servletContext);
}
@Override
protected void configureShiroWeb() {
bindConstant().annotatedWith(Names.named("shiro.globalSessionTimeout")).to(30000L);
bindRealm().to(EgAuthorizingRealm.class).asEagerSingleton();
addFilterChain("/login.jsp", AUTHC);
addFilterChain("/api/*", AUTHC);
}
}
例如授权领域:
package eg.guicejerseyjettyshiro.realms;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
public class EgAuthorizingRealm extends AuthorizingRealm {
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token)
throws AuthenticationException {
UsernamePasswordToken upToken = (UsernamePasswordToken) token;
System.out.println("In EgAuthorizingRealm.doGetAuthenticationInfo for: " + upToken.getUsername() + "/" + new String(upToken.getPassword()) + " - remember=" + upToken.isRememberMe());
return new SimpleAuthenticationInfo(upToken.getUsername(), upToken.getPassword(), getName());
}
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection pc) {
System.out.println("In EgAuthorizingRealm.doGetAuthorizationInfo");
// Doing nothing just now
return null;
}
}
Uuid服务:
package eg.guicejerseyjettyshiro.services;
import javax.inject.Inject;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.subject.Subject;
import eg.guicejerseyjettyshiro.dao.UuidDao;
@Path("/api/uuid")
@Produces({MediaType.APPLICATION_XML})
public class UuidService {
private final UuidDao uuidDao;
@Inject
public UuidService(UuidDao uuidDao) {
this.uuidDao = uuidDao;
}
@GET
public String get() {
Subject currentUser = SecurityUtils.getSubject();
System.out.println("UuidService current user: " + currentUser.getPrincipal().toString());
return "<uuid>" + this.uuidDao.generateUuid().toString() + "</uuid>";
}
}
UuidDao:
package eg.guicejerseyjettyshiro.dao;
import java.util.UUID;
public class UuidDao {
public UUID generateUuid() {
return UUID.randomUUID();
}
}
登录.jsp:
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Please Login</title>
</head>
<body>
<form name="loginForm" action="" method="post">
<table align="left" border="0" cellspacing="0" cellpadding="3">
<tr>
<td>Username:</td>
<td><input type="text" name="username" maxlength="30"></td>
</tr>
<tr>
<td>Password:</td>
<td><input type="password" name="password" maxlength="30"></td>
</tr>
<tr>
<td colspan="2" align="left"><input type="checkbox" name="rememberMe"><font size="2">Remember Me</font></td>
</tr>
<tr>
<td colspan="2" align="right"><input type="submit" name="submit" value="Login"></td>
</tr>
</table>
</form>
</body>
</html>
好吧,我想这就是全部。我知道这很长,非常感谢您阅读到这里。这让我发疯了,所以如果你能给我任何帮助,我将不胜感激!
谢谢,安迪。
最佳答案
感谢 Milan Baran 在 Shiro 用户论坛上回答了这个问题。 github 存储库已更新,这里有一个快速摘要,以防有人感兴趣:
在Bootstrap类中,我们只需要添加一个GuiceFilter,用于/*,根本不需要默认服务器。所以,这变成了:
public static void main(String[] args) throws Exception {
Server server = new Server(8081);
WebAppContext webAppContext = new WebAppContext();
webAppContext.setContextPath("/");
webAppContext.setResourceBase("src/main/webapp/");
webAppContext.setParentLoaderPriority(true);
webAppContext.addEventListener(new EgGuiceServletContextListener());
webAppContext.addFilter(GuiceFilter.class, "/*", null);
server.setHandler(webAppContext);
server.start();
server.join();
}
然后我们需要更新 jersey servlet 模块以绑定(bind) DefaultServlet 和 GuiceContainer,并将通过 GuiceContainer 的过滤器更改为通过/api 而不是/*,如下所示:
public class EgJerseyServletModule extends JerseyServletModule {
@Override
protected void configureServlets() {
bindings();
filters();
}
private void bindings() {
bind(UuidDao.class);
bind(UuidService.class);
bind(DefaultServlet.class).asEagerSingleton();
bind(GuiceContainer.class).asEagerSingleton();
serve("/*").with(DefaultServlet.class);
}
private void filters() {
filter("/*").through(GuiceShiroFilter.class);
filter("/api/*").through(GuiceContainer.class);
}
}
感谢大家的帮助!安迪。
关于jsp - Jetty 在使用 Jersey-Guice-Shiro 栈时找不到 login.jsp,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14059459/
我已阅读 Jersey documentation ,并表示 Jersey 在读取实体后自动关闭连接(例如 response.readEntity(SomeObject.class)) 但是当抛出异常
Jersey vs Jersey (Standalone) vs Jersey with Grizzly vs Jersey with Tomcat - for REST services 有什么区别
如何通过 guice 使用非 Jersey 资源和 Jersey 资源? 我希望“/”由普通 servlet 处理。但我希望 Jersey 处理“/users”。 假设我有一个带@Path("/use
我正在尝试使用 Maven、Apache Tomcat 7.0、Eclipse IDE 创建一个基本的 RESTful 应用程序。我在 google 提供的一些示例代码中遇到了 jersey-serv
我已经从 Jersey 1.7 升级到 2.16,但 Jersey 似乎无法找到我的资源(请参阅下面的堆栈)。任何想法发生了什么?我尝试在扩展 ResourceConfig 的自定义应用程序类中初始化
我正在使用 com.yammer.dropwizard.config.Environment addProvider 方法在 Jersey 中注册提供程序。我也有一个自定义提供程序,它执行类似于 Dr
在 Jersey 1.x 中,您可以使用 ContainerRequest.getFormParameters()对表单数据进行请求过滤,但我在 Jersey 2.x 中看不到明显的等价物。我已经实现
我正在使用Jersey的集成Jackson处理将传入的JSON转换为POJO,例如: @POST @Consumes(MediaType.APPLICATION_JSON) public Respon
我正在尝试以编程方式创建 Jersey 资源(没有注释)。我有一个将 Name 和 id 作为输入参数的方法 raiseAlarm。我想从 JSON 输入中获取名称,并且我希望 id 来自路径参数。代
Dropwizard official documentation Jersey 客户端不可测试,有人有 dropwizard Jersey 客户端样本吗? 最佳答案 我发现在 Dropwizard
我一直在寻找解决这个问题的方法,但没有成功。我发现的最新帖子可以追溯到 2010 年。我正在使用带有嵌入式 grizzly 2.2.1 的 Jersey 1.12。 如果我理解正确,除非我将 Jers
我想开发一个 Web API,它将生成和使用 JSON 和 XML 数据。 我已经使用JAXB来支持XML,并且工作正常。现在我想添加 JSON 类型。我研究了不同的教程,所有教程都使用不同的依赖项,
如此处所述:http://wikis.sun.com/display/Jersey/WADL 我在 Tomcat 6 中使用 Jersey 1.4。 我已经尝试了所有可能的带有“/applicatio
我是jax-rs的新手,并且已经用jersey和glassfish构建了Web服务。 我需要的是一种方法,服务启动后即被称为。在这种方法中,我想加载自定义配置文件,设置一些属性,编写日志等等。 我尝试
当客户端请求 Not Acceptable MIME 类型时,如何防止 Jersey 在客户端发送 HTML 页面?我想使用 ExceptionMapper,但我不确定要捕获什么异常,或者这是否是处理
我试图在它的 JSON 被解码后拦截一个资源调用。通过阅读一些论坛和帖子,我发现我可以通过实现 来做到这一点。 org.glassfish.jersey.server.spi.internal.Res
我的 webapp 包含一个库,其中包含一个用 @javax.ws.rs.ext.Provider 注释的类。 .如果存在此类,我的 web 应用程序(在 EAR 中部署为 WAR)将无法启动并显示以
我想自定义404响应,即服务器(不是我)在找不到请求的资源时抛出(或自己抛出一个自定义的WebApplicationException,如果可以测试一个应用程序中是否存在请求的资源)?资源列表存储在某
我有一个受 Shibboleth(SSO 实现)保护的 Jersey API。 Shibboleth 将登录用户的 ID 放入请求属性中。在后端,我使用 Shiro 进行授权。 Shiro 希望了解登
我目前正在使用 Jersey 返回 JSON。我该如何返回 JSONP?例如我当前的RESTful方法是: @GET @Produces(MediaType.APPLICATION_JSON) pub
我是一名优秀的程序员,十分优秀!