springboot shrio整合后,默认在未登录的情况下shrio会将请求重定向到登陆页面,但是我配置了nginx的https后,发起的请求是https,但是如果是未登录,shrio则会将请求重定向到登陆页面,这个时候出现问题,这个重定向的请求是http,前端js就会报错。
解决思路,配置shrio自定义拦截器,如果是未登录的 返回对ajax友好的json数据。
并且我们希望前端能根据返回的数据进行判断用户是否登录,所以这里要对ajax进行封装。
关键步骤:添加shrio自定义拦截器
package com.ning.config;
import java.io.IOException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import org.apache.shiro.web.filter.authc.UserFilter;
import com.alibaba.fastjson.JSON;
import com.ning.utils.R;
public class MyFilter extends UserFilter{
@Override
protected void redirectToLogin(ServletRequest request, ServletResponse response) throws IOException {
response.setContentType("application/json; charset=utf-8");
response.getWriter().print(JSON.toJSON(R.error(403, "请登录")));
}
}
将拦截器添加到shrio配置类中
package com.ning.config;
import java.util.LinkedHashMap;
import java.util.Map;
import javax.servlet.Filter;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.session.mgt.SessionManager;
import org.apache.shiro.spring.LifecycleBeanPostProcessor;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.ning.utils.UserRealm;
/**
* Shiro配置
*
*/
@Configuration
public class ShiroConfig {
@Bean(name = "sessionManager")
public SessionManager sessionManager(){
DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();
//设置session过期时间为1小时(单位:毫秒),默认为30分钟
sessionManager.setGlobalSessionTimeout(60 * 60 * 1000 * 24 * 7);
sessionManager.setSessionValidationSchedulerEnabled(true);
sessionManager.setSessionIdUrlRewritingEnabled(false);
return sessionManager;
}
@Bean(name = "securityManager")
public SecurityManager securityManager(UserRealm userRealm, SessionManager sessionManager) {
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
//Realm 主要是从realm中获取相应的身份信息
securityManager.setRealm(userRealm);
securityManager.setSessionManager(sessionManager);
return securityManager;
}
//传统方式是使用web.xml配置的。在shiro中使用@Bean注解方式实现过滤器。
@Bean("shiroFilter")
public ShiroFilterFactoryBean shirFilter(SecurityManager securityManager) {
ShiroFilterFactoryBean shiroFilter = new ShiroFilterFactoryBean();
shiroFilter.setSecurityManager(securityManager);
Map filters = shiroFilter.getFilters();
filters.put("authc", new MyFilter());
shiroFilter.setFilters(filters);
//shiroFilter.setLoginUrl("/login.html");//默认访问的首页面
//shiroFilter.setSuccessUrl("/index.html");
//shiroFilter.setUnauthorizedUrl("/");
//anon代表是匿名访问方式,比如index.html是匿名访问的即不区分用户、谁都可以访问。
Map filterMap = new LinkedHashMap<>();
filterMap.put("/public/**", "anon");
filterMap.put("/favicon.ico", "anon");
filterMap.put("/public/plugins/**", "anon");
filterMap.put("/public/plugins/UE/jsp/**", "anon");
filterMap.put("/webjars/**", "anon");
filterMap.put("/api/**", "anon");
filterMap.put("/originInfo/**", "anon");
filterMap.put("/app/app/checkVersion", "anon");//app检查版本
filterMap.put("/app/app/getNewVersion", "anon");//app下载最新版本
//swagger配置
filterMap.put("/swagger**", "anon");
filterMap.put("/v2/api-docs", "anon");
filterMap.put("/swagger-resources/configuration/ui", "anon");
filterMap.put("/login.html", "anon");
filterMap.put("/index.html", "anon");
filterMap.put("/json", "anon");
filterMap.put("/sys/login", "anon");
filterMap.put("/captcha.jpg", "anon");//认证码
filterMap.put("/upload/ckUploadImg", "anon");
filterMap.put("/upload/**", "anon");
filterMap.put("/upload/ck/**", "anon");
//authc代表是必须认证访问的。/**代表是除上面配置以外的其它资源。
filterMap.put("/**", "authc");
shiroFilter.setFilterChainDefinitionMap(filterMap);
return shiroFilter;
}
@Bean(name = "lifecycleBeanPostProcessor")
public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
return new LifecycleBeanPostProcessor();
}
@Bean
public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
DefaultAdvisorAutoProxyCreator proxyCreator = new DefaultAdvisorAutoProxyCreator();
proxyCreator.setProxyTargetClass(true);
return proxyCreator;
}
@Bean
public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
AuthorizationAttributeSourceAdvisor advisor = new AuthorizationAttributeSourceAdvisor();
advisor.setSecurityManager(securityManager);
return advisor;
}
}
请注意关键部分代码
Map filters = shiroFilter.getFilters();
filters.put("authc", new MyFilter());
这里filters.put("authc", new MyFilter());map添加的key值必须为authc,之前我自定义是无效的。
这样如果用户在未登录状态发起请求,就会返回我们自定义的json字符串。下面是自定义ajax:
function Ajax(type,url,param,callback,isjson){
var contentType = "application/x-www-form-urlencoded;charset=UTF-8";
if(isjson){
contentType = "application/json;charset=UTF-8";
}
$.ajax({
type: type,
url: url,
data: param,
contentType:contentType,
success: function(r){
if(r.code == 403){
alert("请重新登陆")
}else{
callback(r);
}
}
})
}
Ajax("post","/json",{"json":6667},function(data){
console.log(data)
})
对ajax的成功回调函数进行封装,也可以对请求参数进行封装。方便使用。