如何更正Shiro注销代码(用户在执行注销后仍然可以访问页面)?
How to correct Shiro logout code (user can still access pages after log out is executed)?
我正在实施 Shiro 安全性,我的登录实施工作正常,但注销似乎没有注销用户。我有一个注销 link,它指向一个调用 Shiro 注销代码的自定义 servlet。代码执行(我可以单步执行代码并且在控制台中可以看到日志输出)但是,如果我按下浏览器中的后退按钮并重新加载原始页面,我可以到达该页面并且不会要求我重新 -输入我的登录凭据。
我需要做什么来解决这个问题?
servlet 代码如下所示。完整的例子在这里:
https://github.com/NACHC-CAD/web-security-example
Servlet 代码:
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
Subject subject = SecurityUtils.getSubject();
log.info("Doing log off for user: ");
if(subject != null && subject.isAuthenticated()) {
subject.logout();
log.info("Subject has been logged off");
} else {
log.info("USER NOT FOUND, NOT LOGGED OFF");
}
log.info("User has been log offed");
}
登录码:
@Slf4j
public class MyAppRealm extends SimpleAccountRealm {
/**
* Authentication method is based on SimpleAccountRealm doGetAuthenticationInfo(AuthenticationToken token) method.
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
log.info("* * * DOING CUSTOM AUTHN * * *");
UsernamePasswordToken upToken = (UsernamePasswordToken) token;
String uid = upToken.getUsername();
String pwd = new String(upToken.getPassword());
log.info("Doing login for user: " + uid);
SimpleAccount account = null;
if(uid.equals("foo") && pwd.equals("bar")) {
account = new SimpleAccount("foo", "bar", getName());
account.setCredentials("bar");
account.addRole("ROLE_ADMIN");
} else {
account = null;
log.info("Credentials failed for user: " + uid);
}
// account.setObjectPermissions(permissions);
log.info("Done with custom authn");
return account;
}
/**
* Authorization method is based on SimpleAccountRealm doGetAuthorizationInfo(PrincipalCollection principals) method.
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
log.info("* * * DOING CUSTOM AUTHZ * * *");
String username = getUsername(principals);
USERS_LOCK.readLock().lock();
try {
SimpleAccount rtn = this.users.get(username);
log.info("Done with custom authz.");
return rtn;
} finally {
USERS_LOCK.readLock().unlock();
}
}
}
web.xml
<!--
*
* shiro stuff
*
-->
<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
# ---
#
# ini file for shiro
#
# ---
[main]
myRealm = org.nachc.examples.websecurity.shiro.util.realm.MyAppRealm
securityManager.realms = $myRealm
[users]
admin = admin, ROLE_ADMIN
[roles]
ROLE_ADMIN = *
[urls]
/app/** = authcBasic
--- 编辑 --------------------------
浏览器似乎正在缓存凭据并在访问同一页面时重新发送。即使在新选项卡中使用隐身 window,如果我访问同一页面,浏览器也会将基本身份验证凭据添加到请求中。看起来这是由 Chrome 添加的,作为他们对基本身份验证的标准处理的一部分。此处提供更多信息:How to clear basic authentication details in chrome(提供的用于清除详细信息的方法非常手动且依赖于用户,如果您需要确保注销用户需要重新提供凭据,则不太适合)。
--- 编辑 2 ------------------
我能够根据下面接受的答案的建议,使用 Shiro 实施基于表单的身份验证来解决这个问题。完整的例子在这里:
https://github.com/NACHC-CAD/web-security-example
这是 BASIC 身份验证的常见问题。
您需要支持基本身份验证吗?如果没有,您可以使用登录表单,请参阅此处的示例:https://github.com/apache/shiro/blob/main/samples/web/src/main/webapp/WEB-INF/shiro.ini#L54-L60
如果您需要为 Web 浏览器同时支持 BASIC 身份验证和表单,您可以这样做:
/app/** = authcBasic[permissive], authc
注意:这是记忆中的,因此请相应地进行测试;)
我正在实施 Shiro 安全性,我的登录实施工作正常,但注销似乎没有注销用户。我有一个注销 link,它指向一个调用 Shiro 注销代码的自定义 servlet。代码执行(我可以单步执行代码并且在控制台中可以看到日志输出)但是,如果我按下浏览器中的后退按钮并重新加载原始页面,我可以到达该页面并且不会要求我重新 -输入我的登录凭据。
我需要做什么来解决这个问题?
servlet 代码如下所示。完整的例子在这里:
https://github.com/NACHC-CAD/web-security-example
Servlet 代码:
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
Subject subject = SecurityUtils.getSubject();
log.info("Doing log off for user: ");
if(subject != null && subject.isAuthenticated()) {
subject.logout();
log.info("Subject has been logged off");
} else {
log.info("USER NOT FOUND, NOT LOGGED OFF");
}
log.info("User has been log offed");
}
登录码:
@Slf4j
public class MyAppRealm extends SimpleAccountRealm {
/**
* Authentication method is based on SimpleAccountRealm doGetAuthenticationInfo(AuthenticationToken token) method.
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
log.info("* * * DOING CUSTOM AUTHN * * *");
UsernamePasswordToken upToken = (UsernamePasswordToken) token;
String uid = upToken.getUsername();
String pwd = new String(upToken.getPassword());
log.info("Doing login for user: " + uid);
SimpleAccount account = null;
if(uid.equals("foo") && pwd.equals("bar")) {
account = new SimpleAccount("foo", "bar", getName());
account.setCredentials("bar");
account.addRole("ROLE_ADMIN");
} else {
account = null;
log.info("Credentials failed for user: " + uid);
}
// account.setObjectPermissions(permissions);
log.info("Done with custom authn");
return account;
}
/**
* Authorization method is based on SimpleAccountRealm doGetAuthorizationInfo(PrincipalCollection principals) method.
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
log.info("* * * DOING CUSTOM AUTHZ * * *");
String username = getUsername(principals);
USERS_LOCK.readLock().lock();
try {
SimpleAccount rtn = this.users.get(username);
log.info("Done with custom authz.");
return rtn;
} finally {
USERS_LOCK.readLock().unlock();
}
}
}
web.xml
<!--
*
* shiro stuff
*
-->
<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
# ---
#
# ini file for shiro
#
# ---
[main]
myRealm = org.nachc.examples.websecurity.shiro.util.realm.MyAppRealm
securityManager.realms = $myRealm
[users]
admin = admin, ROLE_ADMIN
[roles]
ROLE_ADMIN = *
[urls]
/app/** = authcBasic
--- 编辑 --------------------------
浏览器似乎正在缓存凭据并在访问同一页面时重新发送。即使在新选项卡中使用隐身 window,如果我访问同一页面,浏览器也会将基本身份验证凭据添加到请求中。看起来这是由 Chrome 添加的,作为他们对基本身份验证的标准处理的一部分。此处提供更多信息:How to clear basic authentication details in chrome(提供的用于清除详细信息的方法非常手动且依赖于用户,如果您需要确保注销用户需要重新提供凭据,则不太适合)。
--- 编辑 2 ------------------
我能够根据下面接受的答案的建议,使用 Shiro 实施基于表单的身份验证来解决这个问题。完整的例子在这里:
https://github.com/NACHC-CAD/web-security-example
这是 BASIC 身份验证的常见问题。
您需要支持基本身份验证吗?如果没有,您可以使用登录表单,请参阅此处的示例:https://github.com/apache/shiro/blob/main/samples/web/src/main/webapp/WEB-INF/shiro.ini#L54-L60
如果您需要为 Web 浏览器同时支持 BASIC 身份验证和表单,您可以这样做:
/app/** = authcBasic[permissive], authc
注意:这是记忆中的,因此请相应地进行测试;)