Web 应用程序 Apache Shiro 集成
Web application Apache Shiro integration
我正在尝试了解 Apache Shiro 工作流程以及如何将其集成到我的应用程序中。我无法理解的是如何以及在何处执行登录然后发送重定向?或者 Shiro 会自动执行此操作(因为我在 ini 文件中指定了领域)?我可以发送自定义信息(用户属性)和重定向(通过 Servlet 响应而不是支持 bean)吗?
目前我所了解和掌握的内容:
将 Shiro 侦听器和过滤器添加到 web.xml 文件,以便它可以响应请求:
<listener>
<listener-class>org.apache.shiro.web.env.EnvironmentLoaderListener</listener-class>
</listener>
<filter>
<filter-name>ShiroFilter</filter-name>
<filter-class>org.apache.shiro.web.servlet.ShiroFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>ShiroFilter</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
<dispatcher>INCLUDE</dispatcher>
<dispatcher>ERROR</dispatcher>
</filter-mapping>
创建一个 shiro.ini 文件,您可以在其中配置 Shiro 的一些属性:
[main]
shiro.loginURL = /login.xhtml
myRealm = com.example.shiro.MyRealm
securityManager.realms = $myRealm
[urls]
/account/** = authc
/logout = logout
创建自定义领域class:
@Stateless
@Local(Realm.class)
public class SecurityBean implements Realm{
private EntityManager em;
private TypedQuery<Credential> cQuery;
@Override
public Account getAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
try{
cQuery = em.createNamedQuery("getCredentials", Credential.class);
cQuery.setParameter("userName", ((UsernamePasswordToken) token).getUsername());
Credential c = cQuery.getSingleResult();
boolean b = Encryption.compare(new String(((UsernamePasswordToken) token).getPassword()), c.getSalt(), c.getEncryptedPassword());
if(b){
return c;
}else{
throw new AuthenticationException("Passwords do not match.");
}
}catch(Exception e){
throw new AuthenticationException("Error verifying credentials.");
}
}
@Override
public String getName() {
return "User Realm";
}
@Override
public boolean supports(AuthenticationToken token) {
if(token instanceof UsernamePasswordToken){
return true;
}else{
return false;
}
}
}
其中 Encryption 是一个 class 用于加密和比较密码,Credential 是一个 JPA 实体 class 用于存储用户名和密码:
@NamedQueries({@NamedQuery(name = "getCredentials", query = "SELECT c FROM Credential c WHERE c.userName = :userName"),
@NamedQuery(name = "deleteCredentials", query = "DELETE FROM Credential c WHERE c.userName = :userName")})
@Entity
public class Credential implements Serializable, Account{
private static final long serialVersionUID = 2555682746921997545L;
@Id @GeneratedValue
private long id;
private String userName;
private String encryptedPassword;
private String salt;
private User user;
//... getters/setters...
}
其中 User 是一个 JPA 实体 class,它实际存储用户的应用程序信息。
Shiro 将自动拦截对受限资源的任何请求,并显示定义的登录屏幕。您只需要声明您的应用程序资源所需的身份验证级别。获取您的代码:
[main]
shiro.loginURL = /login.xhtml
myRealm = com.example.shiro.MyRealm
securityManager.realms = $myRealm
[urls]
/account/** = authc
/logout = logout
你是在告诉四郎:
- 要向用户显示的登录屏幕是
/login.xhtml
- 你的 Realm class 是
com.example.shiro.MyRealm
。 Shiro 将实例化它,并将特定于应用程序的安全操作委托给它。您可以在此处编写特定的安全代码。如果我没有理解错的话,你的 SecurityBean
是你的自定义 Realm
,因此它应该重命名为 com.example.shiro.MyRealm
或者你将 myRealm
更改为指向那个 class.
/account/** = authc
:/account/
中的每个资源都需要对用户进行身份验证。因此,如果用户尚未通过身份验证,任何尝试去那里都会导致 Shiro 显示登录页面。
- 当用户转到
/logout
时,shiro 将结束会话
我看到的是您在 [urls]
部分的开头缺少这一行:/login.xhtml = authc
。 /login.xhtml
不限于经过身份验证的用户(否则没有人可以登录),但仍必须为其指定 authc
过滤器,以便它可以处理 url 的登录提交。 'smart' 足以让这些请求按照指定的方式通过
shiro.loginUrl
以上。
顺便说一句,如果您还想拥有一个完整的用户管理解决方案,请查看 Stormpath. We also have a plugin that seamlessly works with Shiro. You can take a look at our sample Stormpath Shiro app
免责声明,我是活跃的 Stormpath 贡献者。
我正在尝试了解 Apache Shiro 工作流程以及如何将其集成到我的应用程序中。我无法理解的是如何以及在何处执行登录然后发送重定向?或者 Shiro 会自动执行此操作(因为我在 ini 文件中指定了领域)?我可以发送自定义信息(用户属性)和重定向(通过 Servlet 响应而不是支持 bean)吗?
目前我所了解和掌握的内容:
将 Shiro 侦听器和过滤器添加到 web.xml 文件,以便它可以响应请求:
<listener>
<listener-class>org.apache.shiro.web.env.EnvironmentLoaderListener</listener-class>
</listener>
<filter>
<filter-name>ShiroFilter</filter-name>
<filter-class>org.apache.shiro.web.servlet.ShiroFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>ShiroFilter</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
<dispatcher>INCLUDE</dispatcher>
<dispatcher>ERROR</dispatcher>
</filter-mapping>
创建一个 shiro.ini 文件,您可以在其中配置 Shiro 的一些属性:
[main]
shiro.loginURL = /login.xhtml
myRealm = com.example.shiro.MyRealm
securityManager.realms = $myRealm
[urls]
/account/** = authc
/logout = logout
创建自定义领域class:
@Stateless
@Local(Realm.class)
public class SecurityBean implements Realm{
private EntityManager em;
private TypedQuery<Credential> cQuery;
@Override
public Account getAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
try{
cQuery = em.createNamedQuery("getCredentials", Credential.class);
cQuery.setParameter("userName", ((UsernamePasswordToken) token).getUsername());
Credential c = cQuery.getSingleResult();
boolean b = Encryption.compare(new String(((UsernamePasswordToken) token).getPassword()), c.getSalt(), c.getEncryptedPassword());
if(b){
return c;
}else{
throw new AuthenticationException("Passwords do not match.");
}
}catch(Exception e){
throw new AuthenticationException("Error verifying credentials.");
}
}
@Override
public String getName() {
return "User Realm";
}
@Override
public boolean supports(AuthenticationToken token) {
if(token instanceof UsernamePasswordToken){
return true;
}else{
return false;
}
}
}
其中 Encryption 是一个 class 用于加密和比较密码,Credential 是一个 JPA 实体 class 用于存储用户名和密码:
@NamedQueries({@NamedQuery(name = "getCredentials", query = "SELECT c FROM Credential c WHERE c.userName = :userName"),
@NamedQuery(name = "deleteCredentials", query = "DELETE FROM Credential c WHERE c.userName = :userName")})
@Entity
public class Credential implements Serializable, Account{
private static final long serialVersionUID = 2555682746921997545L;
@Id @GeneratedValue
private long id;
private String userName;
private String encryptedPassword;
private String salt;
private User user;
//... getters/setters...
}
其中 User 是一个 JPA 实体 class,它实际存储用户的应用程序信息。
Shiro 将自动拦截对受限资源的任何请求,并显示定义的登录屏幕。您只需要声明您的应用程序资源所需的身份验证级别。获取您的代码:
[main]
shiro.loginURL = /login.xhtml
myRealm = com.example.shiro.MyRealm
securityManager.realms = $myRealm
[urls]
/account/** = authc
/logout = logout
你是在告诉四郎:
- 要向用户显示的登录屏幕是
/login.xhtml
- 你的 Realm class 是
com.example.shiro.MyRealm
。 Shiro 将实例化它,并将特定于应用程序的安全操作委托给它。您可以在此处编写特定的安全代码。如果我没有理解错的话,你的SecurityBean
是你的自定义Realm
,因此它应该重命名为com.example.shiro.MyRealm
或者你将myRealm
更改为指向那个 class. /account/** = authc
:/account/
中的每个资源都需要对用户进行身份验证。因此,如果用户尚未通过身份验证,任何尝试去那里都会导致 Shiro 显示登录页面。- 当用户转到
/logout
时,shiro 将结束会话
我看到的是您在 [urls]
部分的开头缺少这一行:/login.xhtml = authc
。 /login.xhtml
不限于经过身份验证的用户(否则没有人可以登录),但仍必须为其指定 authc
过滤器,以便它可以处理 url 的登录提交。 'smart' 足以让这些请求按照指定的方式通过
shiro.loginUrl
以上。
顺便说一句,如果您还想拥有一个完整的用户管理解决方案,请查看 Stormpath. We also have a plugin that seamlessly works with Shiro. You can take a look at our sample Stormpath Shiro app
免责声明,我是活跃的 Stormpath 贡献者。