重写AccessControlFilter的时候一直报下面这个错误,
org.apache.shiro.UnavailableSecurityManagerException: No SecurityManager accessible to the calling code, either bound to the org.apache.shiro.util.ThreadContext or as a vm static singleton. This is an invalid application configuration.
at org.apache.shiro.SecurityUtils.getSecurityManager(SecurityUtils.java:123) ~[shiro-core-1.4.0.jar:1.4.0]
at org.apache.shiro.subject.Subject$Builder.<init>(Subject.java:626) ~[shiro-core-1.4.0.jar:1.4.0]
at org.apache.shiro.SecurityUtils.getSubject(SecurityUtils.java:56) ~[shiro-core-1.4.0.jar:1.4.0]
at com.test.shiro.filter.MyAccessControlFilter.onAccessDenied(MyAccessControlFilter.java:70) ~[classes/:na]
代码:
package com.test.shiro.filter;
import com.test.shiro.service.TokenService;
//import com.test.shiro.shiro.MyUsernamePasswordToken;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.web.filter.AccessControlFilter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* @author Created by pangkunkun on 2017/11/18.
*/
@Component
public class MyAccessControlFilter extends AccessControlFilter {
private static final Logger log= LoggerFactory.getLogger(MyAccessControlFilter.class);
/**
*
* 如果isAccessAllowed返回true则onAccessDenied方法不会继续执行
* 这里可以用来判断一些不被通过的链接(个人备注)
* */
@Override
public boolean isAccessAllowed(ServletRequest servletRequest, ServletResponse servletResponse, Object object) throws Exception{
return false;
}
/**
* 表示当访问拒绝时是否已经处理了;如果返回true表示需要继续处理;如果返回false表示该拦截器实例已经处理了,将直接返回即可。
* onAccessDenied是否执行取决于isAccessAllowed的值,如果返回true则onAccessDenied不会执行;如果返回false,执行onAccessDenied
* 如果onAccessDenied也返回false,则直接返回,不会进入请求的方法(只有isAccessAllowed和onAccessDenied的情况下)
* */
@Override
public boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception{
System.out.println("onAccessDenied");
UsernamePasswordToken token1=new UsernamePasswordToken("admin","admin");
Subject subject= SecurityUtils.getSubject();
try {
subject.login(token1);
// subject.isPermitted("add");
log.info("subject.hasRole(\"user\");"+subject.hasRole("user"));
}catch (Exception e){
log.info("登陆失败");
log.info(e.getMessage());
onLoginFail(response);
return false;
}
log.info("登陆成功");
return true;
}
/**
* 登录失败
* */
private void onLoginFail(ServletResponse response) throws IOException {
log.info("设置返回");
HttpServletResponse httpResponse = (HttpServletResponse) response;
httpResponse.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
// httpResponse.getWriter().write("login error");
}
/**
* TODO 跨域请求
*/
private void dealCrossDomain(){
}
}
查了好多资料感觉都不符合我的问题,后来仔细看异常,有一处This is an invalid application configuration.
这时想到了上面有个@Component注解,这个注解本来想做其它处理的,后来用不到了。将此注解去掉后重新运行OK了。
问题思考,Shiro中的filter是在项目本身的Filter链执行之前加载的,所以感觉这个标签的存在让它没有被正常加载进Shiro的配置中,或者被注册成了Spring的bean,无法被Shiro使用。