spring boot 集成shiro ,使用aspect记录日志不生效

王晓哲 发布于 2018/08/13 14:47
阅读 2K+
收藏 2

现在我用了spring boot shiro 做我权限控制,用spring boot aspect来做我的日志记录,拦截的是controller层。但是现在我的shiro配置没有什么问题,权限可以控制。但是我用aspect记录日志的地方有问题,不会出现二次代理的异常。就是记录日志的地方,在shiro不授权的地方会生效,控制台会打印日志。比如我的/login,/loginout地方,但是别的地方却不会打印日志,也不会出现异常。也就是除了login的别的/*都被shiro拦了,不会让aop进行执行了。

我也根据下面的这个更改我的配置了,但是好像不是这个问题。

https://alanli7991.github.io/2016/10/21/%E5%88%87%E9%9D%A2%E7%BC%96%E7%A8%8B%E4%B8%89AspectJ%E4%B8%8EShiro%E4%B8%8D%E5%85%BC%E5%AE%B9%E5%92%8CSpring%E4%BA%8C%E6%AC%A1%E4%BB%A3%E7%90%86%E9%94%99%E8%AF%AF%E5%88%86%E6%9E%90/

maven引用的是spring boot shiro和 spring boot aop

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
        </dependency>

我的shiro配置如下:

@Configuration
public class ShiroConfig {

    private final static Logger LOGGER = LoggerFactory.getLogger(ShiroConfig.class);

    @Bean(name = "customRealm")
    public MyShiroRealm customRealm() {
        MyShiroRealm myShiroRealm = new MyShiroRealm();
        return myShiroRealm;
    }

    @Bean(name = "securityManager")
    public DefaultWebSecurityManager defaultWebSecurityManager(MyShiroRealm customRealm) {
        DefaultWebSecurityManager  securityManager = new DefaultWebSecurityManager ();


        //无状态主题工程,禁止创建session
        StatelessDefaultSubjectFactory statelessDefaultSubjectFactory = new StatelessDefaultSubjectFactory();
        securityManager.setSubjectFactory(statelessDefaultSubjectFactory);
        /*
         * 关闭shiro自带的session,详情见文档
         * http://shiro.apache.org/session-management.html#SessionManagement-StatelessApplications%28Sessionless%29
         */
        DefaultSubjectDAO subjectDAO = new DefaultSubjectDAO();
        DefaultSessionStorageEvaluator defaultSessionStorageEvaluator = new DefaultSessionStorageEvaluator();
        defaultSessionStorageEvaluator.setSessionStorageEnabled(false);
        subjectDAO.setSessionStorageEvaluator(defaultSessionStorageEvaluator);

        securityManager.setSubjectDAO(subjectDAO);

        securityManager.setRealm(customRealm);
        securityManager.setSessionManager(defaultSessionManager());
        return securityManager;
    }

    /**
     * 会话管理类 禁用session
     * @return
     */
    @Bean
    public DefaultSessionManager defaultSessionManager(){
        LOGGER.info("=============ShiroConfig.getDefaultSessionManager()======");
        DefaultSessionManager manager = new DefaultSessionManager();
        manager.setSessionValidationSchedulerEnabled(false);
        return manager;
    }

    @Bean
    @DependsOn("lifecycleBeanPostProcessor")
    public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
        DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
        // 强制使用cglib,防止重复代理和可能引起代理出错的问题
        defaultAdvisorAutoProxyCreator.setProxyTargetClass(true);
        return defaultAdvisorAutoProxyCreator;
    }

    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(DefaultWebSecurityManager securityManager) {
        AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor
                = new AuthorizationAttributeSourceAdvisor();
        authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
        return authorizationAttributeSourceAdvisor;
    }

    @Bean(name = "lifecycleBeanPostProcessor")
    public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
        return new LifecycleBeanPostProcessor();
    }

    @Bean(name = "shiroFilter")
    public ShiroFilterFactoryBean shiroFilterFactoryBean(DefaultWebSecurityManager securityManager) {
        LOGGER.info("===========init shiroFilterFactory============");
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        // 添加自己的过滤器并且取名为jwt
        Map<String, Filter> filterMap = Maps.newHashMap();
        filterMap.put("jwtFilter", new JWTFilter());
        shiroFilterFactoryBean.setFilters(filterMap);

        shiroFilterFactoryBean.setSecurityManager(securityManager);
        shiroFilterFactoryBean.setUnauthorizedUrl("/401");

        Map<String, String> filterChainDefinitionMap = Maps.newLinkedHashMap();
        //注意过滤器配置顺序 不能颠倒
        //配置退出 过滤器,其中的具体的退出代码Shiro已经替我们实现了,登出后跳转配置的loginUrl
        filterChainDefinitionMap.put("/401", "anon");

        // 配置不会被拦截的链接 顺序判断
        filterChainDefinitionMap.put("/static/**", "anon");
        filterChainDefinitionMap.put("/logout", "anon");
        filterChainDefinitionMap.put("/login", "anon");
        filterChainDefinitionMap.put("/**", "jwtFilter");
        //配置shiro默认登录界面地址,前后端分离中登录界面跳转应由前端路由控制,后台仅返回json数据
        shiroFilterFactoryBean.setLoginUrl("/admin/unAuth");
        // 登录成功后要跳转的链接
//        shiroFilterFactoryBean.setSuccessUrl("/index");
        //未授权界面
        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);

        return shiroFilterFactoryBean;
    }

    /**
     * 注册全局异常处理
     * @return
     */
    @Bean(name = "exceptionHandler")
    public HandlerExceptionResolver handlerExceptionResolver(){
        return new GlobalExceptionResolver();
    }
}

记录web的Log配置

@Aspect
@Component
public class WebLog {

    private final static Logger LOGGER = LoggerFactory.getLogger(WebLog.class);

    @Pointcut("execution(public * com.fubt.admin.controller.LoginController.sendCode(..))")
    public void webLog() {
    }

    @Before(value = "webLog()")
    @Order(1)
    public void doBefore(JoinPoint joinPoint) {
        // 接收到请求,记录请求内容
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        // 记录下请求内容
        LOGGER.info("URL : " + request.getRequestURL().toString());
        LOGGER.info("HTTP_METHOD : " + request.getMethod());
        LOGGER.info("IP : " + request.getRemoteAddr());
        LOGGER.info("CLASS_METHOD : " + joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName());
        LOGGER.info("ARGS : " + Arrays.toString(joinPoint.getArgs()));

    }

    @AfterReturning(returning = "ret", pointcut = "webLog()")
    @Order(2)
    public void doAfterReturning(Object ret) {
        // 处理完请求,返回内容
        LOGGER.info("RESPONSE : " + ret.toString());
    }

}

请教各位大神怎么解决aop拦截controller不生效的问题??

加载中
0
p
polaris_he
enable asptctj annotation了吗
h
hodone
回复 @王晓哲 : 解决了吗?
王晓哲
王晓哲
回复 @polaris_he : 你说的对,但是最终他也会进入servlet的,这个应该也会让aop代理到吧?
p
polaris_he
回复 @王晓哲 : 你是用filter拦截的啊,filter优先级比servlet高,filter拦截了就不会进入DispatcherServlet了,这种日志还是建议在filter中做
王晓哲
王晓哲
开启了,spring的aop是自动启用的,spring.aop.proxy-target-class=true,这个配置我也是加了的
返回顶部
顶部