相关文章
Shiro系列教程 AccessControlFilter源码分析
Shiro系列教程拦截器Filter源码分析
AnonymousFilter
//允许匿名访问
public class AnonymousFilter extends PathMatchingFilter {
@Override
protected boolean onPreHandle(ServletRequest request, ServletResponse response, Object mappedValue) {
// 返回true 允许匿名用户访问
return true;
}
}
UserFilter
//登录用户与记住我的用户均可通过
public class UserFilter extends AccessControlFilter {
protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) {
//如果访问登录
if (isLoginRequest(request, response)) {
return true;
} else {
Subject subject = getSubject(request, response);
//如果没有登录账户或记住我的用户则拒绝继续执行
return subject.getPrincipal() != null;
}
}
//如果isAccessAllowed返回false 则执行这个方法
protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
//保存请求路径调转到登录页面
saveRequestAndRedirectToLogin(request, response);
return false;
}
}
AuthenticationFilter
//必须登录才能通过此filter
public abstract class AuthenticationFilter extends AccessControlFilter {
//成功后回调URL
public static final String DEFAULT_SUCCESS_URL = "/";
private String successUrl = DEFAULT_SUCCESS_URL;
public String getSuccessUrl() {
return successUrl;
}
public void setSuccessUrl(String successUrl) {
this.successUrl = successUrl;
}
//只有登录成功后的用户才能继续访问
protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) {
Subject subject = getSubject(request, response);
return subject.isAuthenticated();
}
//跳转到之前被拦截的URL
protected void issueSuccessRedirect(ServletRequest request, ServletResponse response) throws Exception {
WebUtils.redirectToSavedRequest(request, response, getSuccessUrl());
}
}
FormAuthenticationFilter
public class FormAuthenticationFilter extends AuthenticatingFilter {
public static final String DEFAULT_ERROR_KEY_ATTRIBUTE_NAME = "shiroLoginFailure";
//表单属性
public static final String DEFAULT_USERNAME_PARAM = "username";
public static final String DEFAULT_PASSWORD_PARAM = "password";
public static final String DEFAULT_REMEMBER_ME_PARAM = "rememberMe";
private static final Logger log = LoggerFactory.getLogger(FormAuthenticationFilter.class);
private String usernameParam = DEFAULT_USERNAME_PARAM;
private String passwordParam = DEFAULT_PASSWORD_PARAM;
private String rememberMeParam = DEFAULT_REMEMBER_ME_PARAM;
private String failureKeyAttribute = DEFAULT_ERROR_KEY_ATTRIBUTE_NAME;
public FormAuthenticationFilter() {
setLoginUrl(DEFAULT_LOGIN_URL);
}
@Override
public void setLoginUrl(String loginUrl) {
String previous = getLoginUrl();
if (previous != null) {
this.appliedPaths.remove(previous);
}
super.setLoginUrl(loginUrl);
if (log.isTraceEnabled()) {
log.trace("Adding login url to applied paths.");
}
this.appliedPaths.put(getLoginUrl(), null);
}
//如果父类isAccessAllowed返回false 则执行下面逻辑
protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
//判断当前请求是否访问登页面
if (isLoginRequest(request, response)) {
//如果是post提交
if (isLoginSubmission(request, response)) {
if (log.isTraceEnabled()) {
log.trace("Login submission detected. Attempting to execute login.");
}
//调用自动登录逻辑
return executeLogin(request, response);
} else {
if (log.isTraceEnabled()) {
log.trace("Login page view.");
}
//allow them to see the login page ;)
//返回true放用户可以看见登录页面
return true;
}
} else {
if (log.isTraceEnabled()) {
log.trace("Attempting to access a path which requires authentication. Forwarding to the " +
"Authentication url [" + getLoginUrl() + "]");
}
//保存请求页面 调转到登录页
saveRequestAndRedirectToLogin(request, response);
return false;
}
}
//判断当前请求是否post提交数据
@SuppressWarnings({"UnusedDeclaration"})
protected boolean isLoginSubmission(ServletRequest request, ServletResponse response) {
return (request instanceof HttpServletRequest) && WebUtils.toHttp(request).getMethod().equalsIgnoreCase(POST_METHOD);
}
//创建token 拿到用户名密码等参数
protected AuthenticationToken createToken(ServletRequest request, ServletResponse response) {
String username = getUsername(request);
String password = getPassword(request);
return createToken(username, password, request, response);
}
//用户是否选择了记住我
protected boolean isRememberMe(ServletRequest request) {
return WebUtils.isTrue(request, getRememberMeParam());
}
//登录成功则跳转到上次拦截的页面
protected boolean onLoginSuccess(AuthenticationToken token, Subject subject,
ServletRequest request, ServletResponse response) throws Exception {
issueSuccessRedirect(request, response);
return false;
}
protected boolean onLoginFailure(AuthenticationToken token, AuthenticationException e,
ServletRequest request, ServletResponse response) {
if (log.isDebugEnabled()) {
log.debug( "Authentication exception", e );
}
setFailureAttribute(request, e);
//login failed, let request continue back to the login page:
return true;
}
protected void setFailureAttribute(ServletRequest request, AuthenticationException ae) {
String className = ae.getClass().getName();
request.setAttribute(getFailureKeyAttribute(), className);
}
protected String getUsername(ServletRequest request) {
return WebUtils.getCleanParam(request, getUsernameParam());
}
protected String getPassword(ServletRequest request) {
return WebUtils.getCleanParam(request, getPasswordParam());
}
}
RolesAuthorizationFilter
public class RolesAuthorizationFilter extends AuthorizationFilter {
@SuppressWarnings({"unchecked"})
public boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) throws IOException {
Subject subject = getSubject(request, response);
String[] rolesArray = (String[]) mappedValue;
//判断是否设置需要角色
if (rolesArray == null || rolesArray.length == 0) {
//no roles specified, so nothing to check - allow access.
return true;
}
Set roles = CollectionUtils.asSet(rolesArray);
//判断当前用户是否需要角色
return subject.hasAllRoles(roles);
}
}
PermissionsAuthorizationFilter
public class PermissionsAuthorizationFilter extends AuthorizationFilter {
public boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) throws IOException {
Subject subject = getSubject(request, response);
String[] perms = (String[]) mappedValue;
//判断当前用户是否拥有权限
boolean isPermitted = true;
if (perms != null && perms.length > 0) {
if (perms.length == 1) {
if (!subject.isPermitted(perms[0])) {
isPermitted = false;
}
} else {
if (!subject.isPermittedAll(perms)) {
isPermitted = false;
}
}
}
return isPermitted;
}
}
public class PortFilter extends AuthorizationFilter {
public static final int DEFAULT_HTTP_PORT = 80;
public static final String HTTP_SCHEME = "http";
private int port = DEFAULT_HTTP_PORT;
public int getPort() {
return port;
}
public void setPort(int port) {
this.port = port;
}
protected int toPort(Object mappedValue) {
String[] ports = (String[]) mappedValue;
if (ports == null || ports.length == 0) {
return getPort();
}
if (ports.length > 1) {
throw new ConfigurationException("PortFilter can only be configured with a single port. You have " +
"configured " + ports.length + ": " + StringUtils.toString(ports));
}
return Integer.parseInt(ports[0]);
}
//根据客户端请求端口判断是否拦截
protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) throws Exception {
int requiredPort = toPort(mappedValue);
int requestPort = request.getServerPort();
return requiredPort == requestPort;
}
protected String getScheme(String requestScheme, int port) {
if (port == DEFAULT_HTTP_PORT) {
return HTTP_SCHEME;
} else if (port == SslFilter.DEFAULT_HTTPS_PORT) {
return SslFilter.HTTPS_SCHEME;
} else {
return requestScheme;
}
}
//跳转到指定端口
@Override
protected boolean onAccessDenied(ServletRequest request, ServletResponse response, Object mappedValue) throws IOException {
//just redirect to the specified port:
int port = toPort(mappedValue);
String scheme = getScheme(request.getScheme(), port);
StringBuilder sb = new StringBuilder();
sb.append(scheme).append("://");
sb.append(request.getServerName());
if (port != DEFAULT_HTTP_PORT && port != SslFilter.DEFAULT_HTTPS_PORT) {
sb.append(":");
sb.append(port);
}
if (request instanceof HttpServletRequest) {
sb.append(WebUtils.toHttp(request).getRequestURI());
String query = WebUtils.toHttp(request).getQueryString();
if (query != null) {
sb.append("?").append(query);
}
}
WebUtils.issueRedirect(request, response, sb.toString());
return false;
}
}
SslFilter
public class SslFilter extends PortFilter {
public static final int DEFAULT_HTTPS_PORT = 443;
public static final String HTTPS_SCHEME = "https";
public SslFilter() {
setPort(DEFAULT_HTTPS_PORT);
}
@Override
protected String getScheme(String requestScheme, int port) {
if (port == DEFAULT_HTTP_PORT) {
return PortFilter.HTTP_SCHEME;
} else {
return HTTPS_SCHEME;
}
}
@Override
protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) throws Exception {
//调用父类方法判断请求端口 并且是SSL连接
return super.isAccessAllowed(request, response, mappedValue) && request.isSecure();
}
}