shiro整合springboot前后端分离
本文实例为大家分享了shiro整合springboot前后端分离的具体代码,供大家参考,具体内容如下
1、shiro整合springboot的配置
packagecom.hisi.config;
importjava.util.LinkedHashMap;
importjava.util.Map;
importjavax.servlet.Filter;
importorg.apache.shiro.session.mgt.eis.MemorySessionDAO;
importorg.apache.shiro.session.mgt.eis.SessionDAO;
importorg.apache.shiro.spring.LifecycleBeanPostProcessor;
importorg.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
importorg.apache.shiro.spring.web.ShiroFilterFactoryBean;
importorg.apache.shiro.web.mgt.DefaultWebSecurityManager;
importorg.apache.shiro.web.session.mgt.DefaultWebSessionManager;
importorg.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
importorg.springframework.context.annotation.Bean;
importorg.springframework.context.annotation.Configuration;
importorg.springframework.context.annotation.DependsOn;
importcom.hisi.shiro.LoginAuthorizationFilter;
importcom.hisi.shiro.RestFilter;
importcom.hisi.shiro.UserRealm;
/**
*shiro权限管理的配置
*@authorxuguoqin
*@date2018年5月4日
*@version1.0
*/
@Configuration
publicclassShiroConfig{
/**
*安全管理器
*@paramrealm
*@return
*/
@Bean
publicDefaultWebSecurityManagersecurityManager(){
DefaultWebSecurityManagersecurityManager=newDefaultWebSecurityManager();
securityManager.setRealm(userRealm());
securityManager.setSessionManager(sessionManager());
returnsecurityManager;
}
/**
*Realm配置
*@return
*/
@Bean
publicUserRealmuserRealm(){
returnnewUserRealm();
}
/**
*SessionDAO配置
*@return
*/
@Bean
publicSessionDAOsessionDAO(){
returnnewMemorySessionDAO();
}
/**
*sessionManager配置
*@paramsessionDAO
*@return
*/
@Bean
publicDefaultWebSessionManagersessionManager(){
DefaultWebSessionManagersessionManager=newDefaultWebSessionManager();
sessionManager.setSessionDAO(sessionDAO());
returnsessionManager;
}
/**
*shiroFilter配置
*@paramsecurityManager
*@return
*/
@Bean
publicShiroFilterFactoryBeanshiroFilterFactoryBean(DefaultWebSecurityManagersecurityManager){
ShiroFilterFactoryBeanshiroFilter=newShiroFilterFactoryBean();
shiroFilter.setSecurityManager(securityManager());
Mapfilters=newLinkedHashMap();
filters.put("token",newLoginAuthorizationFilter());
filters.put("corsFilter",newRestFilter());
shiroFilter.setFilters(filters);
MapfilterChainDefinitionMap=newLinkedHashMap();
filterChainDefinitionMap.put("/user/login","corsFilter,anon");
filterChainDefinitionMap.put("/user/logout","corsFilter,anon");
filterChainDefinitionMap.put("/user/**","corsFilter,token");
shiroFilter.setFilterChainDefinitionMap(filterChainDefinitionMap);
returnshiroFilter;
}
/**
*保证实现了Shiro内部lifecycle函数的bean执行
*/
@Bean
publicLifecycleBeanPostProcessorlifecycleBeanPostProcessor(){
returnnewLifecycleBeanPostProcessor();
}
/**
*启用shrio授权注解拦截方式,AOP式方法级权限检查
*/
@Bean
@DependsOn(value="lifecycleBeanPostProcessor")//依赖其他bean的初始化
publicDefaultAdvisorAutoProxyCreatordefaultAdvisorAutoProxyCreator(){
returnnewDefaultAdvisorAutoProxyCreator();
}
/**
*加入注解的使用,不加入这个注解不生效使用shiro框架提供的切面类,用于创建代理对象
*@paramsecurityManager
*@return
*/
@Bean
publicAuthorizationAttributeSourceAdvisorauthorizationAttributeSourceAdvisor(DefaultWebSecurityManagersecurityManager){
AuthorizationAttributeSourceAdvisorauthorizationAttributeSourceAdvisor=newAuthorizationAttributeSourceAdvisor();
authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
returnauthorizationAttributeSourceAdvisor;
}
}
2、这里配置的两个过滤器RestFilter和LoginAuthorizationFilter,RestFilter是用于解决前后端分离时的跨域问题,服务端在响应头设置可以接受的请求参数
packagecom.hisi.shiro;
importjava.io.IOException;
importjava.util.Optional;
importjavax.servlet.Filter;
importjavax.servlet.FilterChain;
importjavax.servlet.FilterConfig;
importjavax.servlet.ServletException;
importjavax.servlet.ServletRequest;
importjavax.servlet.ServletResponse;
importjavax.servlet.http.HttpServletRequest;
importjavax.servlet.http.HttpServletResponse;
/**
*前后端分离RESTful接口过滤器
*
*@authorxuguoqin
*
*/
publicclassRestFilterimplementsFilter{
@Override
publicvoidinit(FilterConfigfilterConfig)throwsServletException{
}
@Override
publicvoiddoFilter(ServletRequestrequest,ServletResponseresponse,FilterChainchain)
throwsIOException,ServletException{
HttpServletRequestreq=null;
if(requestinstanceofHttpServletRequest){
req=(HttpServletRequest)request;
}
HttpServletResponseres=null;
if(responseinstanceofHttpServletResponse){
res=(HttpServletResponse)response;
}
if(req!=null&&res!=null){
//设置允许传递的参数
res.setHeader("Access-Control-Allow-Headers","Origin,X-Requested-With,Content-Type,Accept,Authorization");
//设置允许带上cookie
res.setHeader("Access-Control-Allow-Credentials","true");
Stringorigin=Optional.ofNullable(req.getHeader("Origin")).orElse(req.getHeader("Referer"));
//设置允许的请求来源
res.setHeader("Access-Control-Allow-Origin",origin);
//设置允许的请求方法
res.setHeader("Access-Control-Allow-Methods","GET,POST,PATCH,PUT,DELETE,OPTIONS");
}
chain.doFilter(request,response);
}
@Override
publicvoiddestroy(){
}
}
前者ajax请求的时候应该带上参数
$.ajax({
type:"GET",
url:url,
xhrFields:{
withCredentials:true//携带跨域cookie
},
processData:false,
success:function(data){
console.log(data);
}
});
3、LoginAuthorizationFilter主要是对未登录的用户进行过滤然后返回json数据给前端,之前遇到的问题就是shiro配置的loginUrl会导致出现302的问题,在前后端分离的项目中,页面的跳转应该由前端来进行控制,这里前端使用的是vue框架,我需要对shiro中未登录的过滤器FormAuthenticationFilter进行重构
packagecom.hisi.shiro;
importjava.io.IOException;
importjava.io.PrintWriter;
importjava.util.Set;
importjavax.servlet.ServletRequest;
importjavax.servlet.ServletResponse;
importjavax.servlet.http.HttpServletRequest;
importjavax.servlet.http.HttpServletResponse;
importorg.apache.shiro.SecurityUtils;
importorg.apache.shiro.authc.AuthenticationToken;
importorg.apache.shiro.subject.Subject;
importorg.apache.shiro.util.CollectionUtils;
importorg.apache.shiro.web.filter.authc.FormAuthenticationFilter;
importorg.apache.shiro.web.filter.authz.AuthorizationFilter;
importorg.apache.shiro.web.filter.authz.PermissionsAuthorizationFilter;
importorg.slf4j.Logger;
importorg.slf4j.LoggerFactory;
importorg.springframework.beans.factory.annotation.Autowired;
importcom.alibaba.fastjson.JSONObject;
importcom.commons.model.YfpjResult;
importcom.hisi.mapper.HisiUserMapper;
importcom.hisi.model.HisiUser;
importcom.hisi.util.Constant;
importcom.hisi.util.UserAuthStatusEnum;
/**
*shiro未登录反回状态码
*@authorxuguoqin
*@date2018年5月10日
*@version1.0
*/
publicclassLoginAuthorizationFilterextendsFormAuthenticationFilter{
/**
*这个方法是未登录需要执行的方法
*/
@Override
protectedbooleanonAccessDenied(ServletRequestrequest,
ServletResponseresponse)throwsIOException{
HttpServletRequesthttpRequest=(HttpServletRequest)request;
HttpServletResponsehttpResponse=(HttpServletResponse)response;
Subjectsubject=getSubject(request,response);
if(subject.getPrincipal()==null){
//设置响应头
httpResponse.setCharacterEncoding("UTF-8");
httpResponse.setContentType("application/json");
//设置返回的数据
YfpjResultresult=YfpjResult.build(UserAuthStatusEnum.UNLOGIN.getCode(),UserAuthStatusEnum.UNLOGIN.getMsg());
//写回给客户端
PrintWriterout=httpResponse.getWriter();
out.write(JSONObject.toJSONString(result));
//刷新和关闭输出流
out.flush();
out.close();
}else{
//设置响应头
httpResponse.setCharacterEncoding("UTF-8");
httpResponse.setContentType("application/json");
//设置返回的数据
YfpjResultresult=YfpjResult.build(UserAuthStatusEnum.UNAUTH.getCode(),UserAuthStatusEnum.UNAUTH.getMsg());
//写回给客户端
PrintWriterout=httpResponse.getWriter();
out.write(JSONObject.toJSONString(result));
//刷新和关闭输出流
out.flush();
out.close();
}
returnfalse;
}
}
4.以后在进行前后端分离的项目开发的时候,可以前端封装一个允许带cookie的ajax请求,同时封装一个统一的未登录或者未授权状态码的判断
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。