springboot2+shiro访问无授权url时,不想被shiro强制登出

springboot2+shiro访问无授权url时,会被shiro强制登出,但是我想要跳转到指定页面,并且不退出登录,这个怎么实现啊?

要实现在访问无授权的URL时跳转到指定页面并且不退出登录,您可以进行以下步骤:

在Shiro的配置文件中,找到对应的过滤器链配置(可能是shiroFilterFactoryBean或DefaultFilterChainManager),添加一个自定义的过滤器。

创建一个自定义过滤器类,继承Shiro原有的过滤器(如UserFilter),并重写onAccessDenied方法。在该方法中,实现跳转到指定页面的逻辑,而不是强制登出。

示例代码如下:


public class CustomUserFilter extends UserFilter {

    @Override
    protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
        Subject subject = getSubject(request, response);
        if (subject.getPrincipal() == null) {
            // 用户未登录的处理逻辑,可以根据需求进行跳转到登录页面或其他指定页面
            WebUtils.issueRedirect(request, response, "/custom-page");
        } else {
            // 用户已登录但无权限访问的处理逻辑,可以根据需求进行跳转到指定页面
            WebUtils.issueRedirect(request, response, "/unauthorized-page");
        }
        return false;
    }
}

在Shiro的过滤器链配置中,将原有的user过滤器替换为自定义的过滤器。例如,在Spring Boot的配置类中,可以使用addFilterChainDefinition方法配置过滤器链,示例如下:


@Bean
public ShiroFilterFactoryBean shiroFilterFactoryBean() {
    // ...其他配置...

    // 获取过滤器链定义
    Map<String, String> filterChainDefinitionMap = shiroFilterFactoryBean.getFilterChainDefinitionMap();
  
    // 替换原有的user过滤器为自定义过滤器
    filterChainDefinitionMap.put("user", "customUserFilter");

    // ...其他配置...
    
    return shiroFilterFactoryBean;
}

请注意,以上代码仅为示例,具体的配置可能因您的项目架构和需求而有所不同。建议理解Shiro的过滤器链配置和相关概念后,根据项目实际情况进行定制化开发。

【以下回答由 GPT 生成】

对于这个问题,可以通过定制shiro的配置来实现在访问无授权的URL时跳转到指定页面而不退出登录。

首先,在pom.xml文件中添加对shiro的依赖:

<dependency>
    <groupId>org.apache.shiro</groupId>
    <artifactId>shiro-spring-boot-web-starter</artifactId>
    <version>1.7.1</version>
</dependency>

然后,在application.properties文件中配置shiro的相关属性:

# 配置shiro的登录URL
shiro.loginUrl=/login
# 配置shiro的未授权URL
shiro.unauthorizedUrl=/unauthorized

接下来,创建一个自定义的ShiroConfig类,并添加@Configuration注解:

@Configuration
public class ShiroConfig {

    // 定义一个Bean,用于解析shiro的配置
    @Bean
    public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager) {
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        shiroFilterFactoryBean.setSecurityManager(securityManager);

        // 配置拦截器规则
        Map<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
        // 添加需要授权的URL
        filterChainDefinitionMap.put("/admin/**", "authc");
        // 添加无授权跳转的URL
        filterChainDefinitionMap.put("/**", "anon");

        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
        // 配置登录页面的URL
        shiroFilterFactoryBean.setLoginUrl("/login");
        // 配置未授权页面的URL
        shiroFilterFactoryBean.setUnauthorizedUrl("/unauthorized");

        return shiroFilterFactoryBean;
    }

    // 定义一个Bean,用于管理shiro的安全事务
    @Bean
    public SecurityManager securityManager() {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();

        // 配置自定义的realm
        securityManager.setRealm(customRealm());

        return securityManager;
    }

    // 定义一个Bean,用于处理身份认证和授权
    @Bean
    public CustomRealm customRealm() {
        return new CustomRealm();
    }
}

再创建一个自定义的CustomRealm类,继承自AuthorizingRealm,并重写其方法:

public class CustomRealm extends AuthorizingRealm {

    // 授权方法,用于判断用户是否有权限访问指定URL
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        // 获取登录用户的信息
        User user = (User) principalCollection.getPrimaryPrincipal();

        SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
        // 添加用户的权限信息
        authorizationInfo.addStringPermission("admin");

        return authorizationInfo;
    }

    // 认证方法,用于验证用户的身份信息
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        // 获取登录的用户名和密码
        String username = (String) authenticationToken.getPrincipal();
        String password = new String((char[]) authenticationToken.getCredentials());

        // 此处应对用户名和密码进行验证,可以从数据库或其他存储中获取用户信息并进行验证

        // 验证通过后返回认证信息
        return new SimpleAuthenticationInfo(new User(username, password), password, getName());
    }
}

最后,创建登录页面的Controller类和登录页面的html文件:

@Controller
public class LoginController {

    @GetMapping("/login")
    public String login() {
        return "login";
    }
}

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Login</title>
</head>
<body>
    <h1>Login</h1>
    <form method="post" action="/doLogin">
        <input type="text" name="username" required />
        <input type="password" name="password" required />
        <input type="submit" value="Login" />
    </form>
</body>
</html>

至此,已经实现了在访问无授权的URL时跳转到指定页面而不退出登录的功能。



【相关推荐】



如果你已经解决了该问题, 非常希望你能够分享一下解决方案, 写成博客, 将相关链接放在评论区, 以帮助更多的人 ^-^