spring boot shiro整合
2017-12-09 16:29
627 查看
spring boot 整合shiro需要的jar
shiro配置类:
主动触发是通过调用subject.login(token)方法如下:这种方式shiro 的/login=anon
问题小结:
shiro 登录后,样式不显示
可能原因,shiro的filter 把样式给拦截了,注意shiro自定义的filter 不能交给spring 管理,并且要注意拦截器的顺序,shiroFilter 在其他拦截器之前
shiro 报there is no session with id []
产生此原因可能是在代码中的某个地方调用了session.invalidate(),或者shiro 的logout方法,之后又使用了request,session的方法
shiro 点击登录,或者认证成功后继续点击,总是返回到登录页面
正常情况下如果认证失败会返回登录界面,如果认证通过了返回登录界面可以查看设置sessionManager 的setSessionIdCookie()是如何设置cookie的,尽量不要创建新的cookie 而是使用sessionManager.getSessionIdCookie()获取默认的cookie进行设置
<properties> <shiro.version>1.4.0</shiro.version> </properties> <dependencies> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-core</artifactId> <version>${shiro.version}</version> </dependency> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-web</artifactId> <version>${shiro.version}</version> </dependency> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-spring</artifactId> <version>${shiro.version}</version> </dependency> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-ehcache</artifactId> <version>${shiro.version}</version> </dependency> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-guice</artifactId> <version>${shiro.version}</version> </dependency> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-quartz</artifactId> <version>${shiro.version}</version> </dependency> </dependencies>
shiro配置类:
package com.zyc.springboot.config; import java.util.ArrayList; import java.util.Collection; import java.util.LinkedHashMap; import java.util.Map; import javax.servlet.Filter; import org.apache.shiro.authc.credential.HashedCredentialsMatcher; import org.apache.shiro.cache.ehcache.EhCacheManager; import org.apache.shiro.session.SessionListener; import org.apache.shiro.session.mgt.ExecutorServiceSessionValidationScheduler; 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.CookieRememberMeManager; import org.apache.shiro.web.mgt.DefaultWebSecurityManager; import org.apache.shiro.web.servlet.SimpleCookie; import org.apache.shiro.web.session.mgt.DefaultWebSessionManager; import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.DependsOn; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.web.filter.DelegatingFilterProxy; import com.zyc.springboot.shiro.MyFormAuthenticationFilter; import com.zyc.springboot.shiro.MyRealm; @Configuration public class ShiroConfig { @Bean(name = "shiroEhcacheManager") public EhCacheManager getEhCacheManager() { EhCacheManager em = new EhCacheManager(); em.setCacheManagerConfigFile("classpath:ehcache-shiro.xml"); return em; } @Bean(name = "lifecycleBeanPostProcessor") public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() { LifecycleBeanPostProcessor lifecycleBeanPostProcessor = new LifecycleBeanPostProcessor(); return lifecycleBeanPostProcessor; } @Bean(name = "sessionValidationScheduler") public ExecutorServiceSessionValidationScheduler getExecutorServiceSessionValidationScheduler() { ExecutorServiceSessionValidationScheduler scheduler = new ExecutorServiceSessionValidationScheduler(); scheduler.setInterval(900000); //scheduler.setSessionManager(defaultWebSessionManager()); return scheduler; } @Bean public HashedCredentialsMatcher hashedCredentialsMatcher() { HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher(); hashedCredentialsMatcher.setHashAlgorithmName("md5");// 散列算法:这里使用MD5算法; hashedCredentialsMatcher.setHashIterations(1);// 散列的次数,比如散列两次,相当于md5(md5("")); return hashedCredentialsMatcher; } @Bean(name = "defaultWebSecurityManager") public DefaultWebSecurityManager defaultWebSecurityManager(MyRealm myRealm,DefaultWebSessionManager defaultWebSessionManager) { DefaultWebSecurityManager defaultWebSecurityManager = new DefaultWebSecurityManager(); defaultWebSecurityManager.setRealm(myRealm); defaultWebSecurityManager.setCacheManager(getEhCacheManager()); defaultWebSecurityManager.setSessionManager(defaultWebSessionManager); defaultWebSecurityManager.setRememberMeManager(rememberMeManager()); return defaultWebSecurityManager; } @Bean(name = "rememberMeCookie") public SimpleCookie rememberMeCookie() { // 这个参数是cookie的名称,对应前端的checkbox的name = rememberMe SimpleCookie simpleCookie = new SimpleCookie("rememberMe"); // <!-- 记住我cookie生效时间30天 ,单位秒;--> simpleCookie.setMaxAge(259200); return simpleCookie; } /** * cookie管理对象; * * @return */ @Bean(name = "rememberMeManager") public CookieRememberMeManager rememberMeManager() { CookieRememberMeManager cookieRememberMeManager = new CookieRememberMeManager(); cookieRememberMeManager.setCookie(rememberMeCookie()); return cookieRememberMeManager; } @Bean @DependsOn(value = "lifecycleBeanPostProcessor") public MyRealm myRealm() { MyRealm myRealm = new MyRealm(); myRealm.setCacheManager(getEhCacheManager()); myRealm.setCredentialsMatcher(hashedCredentialsMatcher()); return myRealm; } @Bean @DependsOn("lifecycleBeanPostProcessor") public DefaultAdvisorAutoProxyCreator getAutoProxyCreator(){ DefaultAdvisorAutoProxyCreator creator = new DefaultAdvisorAutoProxyCreator(); creator.setProxyTargetClass(true); return creator; } @Bean public AuthorizationAttributeSourceAdvisor getAuthorizationAttributeSourceAdvisor(DefaultWebSecurityManager defaultWebSecurityManager) { AuthorizationAttributeSourceAdvisor aasa = new AuthorizationAttributeSourceAdvisor(); aasa.setSecurityManager(defaultWebSecurityManager); return aasa; } @Bean(name = "sessionManager") public DefaultWebSessionManager defaultWebSessionManager(SessionDao sessionDao) { DefaultWebSessionManager sessionManager = new DefaultWebSessionManager(); sessionManager.setGlobalSessionTimeout(18000000); // //url中是否显示session Id sessionManager.setSessionIdUrlRewritingEnabled(false); // // 删除失效的session sessionManager.setDeleteInvalidSessions(true); sessionManager.setSessionValidationSchedulerEnabled(true); sessionManager.setSessionValidationInterval(18000000); sessionManager.setSessionValidationScheduler(getExecutorServiceSessionValidationScheduler()); //设置SessionIdCookie 导致认证不成功,不从新设置新的cookie,从sessionManager获取sessionIdCookie //sessionManager.setSessionIdCookie(simpleIdCookie()); sessionManager.getSessionIdCookie().setName("session-z-id"); sessionManager.getSessionIdCookie().setPath("/"); sessionManager.getSessionIdCookie().setMaxAge(60*60*24*7); return sessionManager; } @Bean(name = "filterRegistrationBean1") public FilterRegistrationBean filterRegistrationBean() { FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean(); filterRegistrationBean.setFilter(new DelegatingFilterProxy( "shiroFilter")); filterRegistrationBean .addInitParameter("targetFilterLifecycle", "true"); filterRegistrationBean.setEnabled(true); filterRegistrationBean.addUrlPatterns("/"); return filterRegistrationBean; } @Bean(name = "shiroFilter") public ShiroFilterFactoryBean shiroFilterFactoryBean( @Qualifier("defaultWebSecurityManager") DefaultWebSecurityManager defaultWebSecurityManager) { // SecurityUtils.setSecurityManager(defaultWebSecurityManager); ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean(); shiroFilterFactoryBean.setLoginUrl("/login"); shiroFilterFactoryBean.setSuccessUrl("/getMyJsp"); shiroFilterFactoryBean.setUnauthorizedUrl("/login"); shiroFilterFactoryBean.setSecurityManager(defaultWebSecurityManager); Map<String, Filter> filterMap1 = shiroFilterFactoryBean.getFilters(); //自定义的filter 不能交给spring 容器管理,只能使用new 实例化filter filterMap1.put("authc", new MyFormAuthenticationFilter()); shiroFilterFactoryBean.setFilters(filterMap1); Map<String, String> filterMap = new LinkedHashMap<String, String>(); filterMap.put("/static/**", "anon"); filterMap.put("/logout", "logout"); filterMap.put("/login", "authc"); filterMap.put("/**", "authc"); shiroFilterFactoryBean.setFilterChainDefinitionMap(filterMap); return shiroFilterFactoryBean; } }MyRealm类如下:
package com.zyc.springboot.shiro; import java.lang.reflect.InvocationTargetException; import org.apache.commons.beanutils.BeanUtils; import org.apache.shiro.authc.AuthenticationException; import org.apache.shiro.authc.AuthenticationInfo; import org.apache.shiro.authc.AuthenticationToken; import org.apache.shiro.authc.SimpleAuthenticationInfo; import org.apache.shiro.authz.AuthorizationInfo; import org.apache.shiro.realm.AuthorizingRealm; import org.apache.shiro.realm.Realm; import org.apache.shiro.subject.PrincipalCollection; import com.zyc.springboot.entity.User; public class MyRealm extends AuthorizingRealm { /** * 权限认证 */ @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) { // TODO Auto-generated method stub //获取登录用户的信息,在认证时存储的是ShiroUser 所以得到的就是ShiroUser //在其他地方也可通过SecurityUtils.getSubject().getPrincipals()获取用户信息 ShiroUser sysUser = (ShiroUser) principals.getPrimaryPrincipal(); //权限字符串 List<String> permissions=new ArrayList<>(); //从数 e550 据库中获取对应权限字符串并存储permissions //角色字符串 List<String> roles=new ArrayList<>(); //从数据库中获取对应角色字符串并存储roles SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo(); simpleAuthorizationInfo.addStringPermissions(permissions); simpleAuthorizationInfo.addRoles(roles);//角色类型 return simpleAuthorizationInfo; } /** * 登录验证 */ @Override protected AuthenticationInfo doGetAuthenticationInfo( AuthenticationToken arg0) throws AuthenticationException { System.out.println("认证====="); String userName=((MyAuthenticationToken) arg0).getUsername(); char[] password=((MyAuthenticationToken) arg0).getPassword(); User user=new User();//根据用户名密码获取user,这里不在连接数据库 user.setPassword("e10adc3949ba59abbe56e057f20f883e");//123456 md5加密后的值 user.setUserName("zyc");//user信息 本该从数据库中获取,这里为了简单,直接模拟 if(user==null){ throw new AuthenticationException("用户名密码错误"); } ShiroUser shiroUser=new ShiroUser();//自定义的用户信息类,在shiro中存储使用 try { BeanUtils.copyProperties(shiroUser, user);//user信息赋给shiroUser } catch (IllegalAccessException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (InvocationTargetException e) { // TODO Auto-generated catch block e.printStackTrace(); } SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(shiroUser, user.getPassword(), this.getName()); return simpleAuthenticationInfo; } }自定义filter MyFormAuthenticationFilter如下
package com.zyc.springboot.shiro; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.annotation.WebFilter; import org.apache.shiro.authc.AuthenticationException; import org.apache.shiro.authc.AuthenticationToken; import org.apache.shiro.authc.IncorrectCredentialsException; import org.apache.shiro.authc.LockedAccountException; import org.apache.shiro.authc.UnknownAccountException; import org.apache.shiro.subject.Subject; import org.apache.shiro.web.filter.authc.FormAuthenticationFilter; import org.apache.shiro.web.util.WebUtils; import org.springframework.core.annotation.Order; public class MyFormAuthenticationFilter extends FormAuthenticationFilter { // 登录失败,异常抛出 @Override protected boolean onLoginFailure(AuthenticationToken token, AuthenticationException e, ServletRequest request, ServletResponse response) { String className = e.getClass().getName(); if (e != null && !UnknownAccountException.class.getName().equals(className) && !IncorrectCredentialsException.class.getName().equals( className) && !LockedAccountException.class.getName().equals(className)) { // 用户被锁定 e.printStackTrace(); // 非验证异常抛出 } return super.onLoginFailure(token, e, request, response); } // 重写认证通过后的页面跳转,shiro会默认跳转到上一次请求的页面,不适用于iframe的框架 @Override protected void issueSuccessRedirect(ServletRequest request, ServletResponse response) throws Exception { // 认证通过后的跳转地址 System.out.println("认证通过后的跳转地址"+getSuccessUrl()); WebUtils.issueRedirect(request, response, getSuccessUrl(), null, true); } @Override protected AuthenticationToken createToken(ServletRequest request, ServletResponse response) { System.out.println("create Token"); String username = getUsername(request); String password = getPassword(request); boolean remberMe = isRememberMe(request); String host = ""; String captcha = ""; String ipAddr = ""; return new MyAuthenticationToken(username, password, remberMe, host, captcha, ipAddr); } }自定义token类如下:
package com.zyc.springboot.shiro; import org.apache.shiro.authc.UsernamePasswordToken; /** * 用来存储验证码等其他信息 * @author Administrator * */ public class MyAuthenticationToken extends UsernamePasswordToken { /** * */ private static final long serialVersionUID = -2681757716434500100L; private String captcha; private String ipAddr; public MyAuthenticationToken(String username,String password,boolean rememberMe,String host,String captcha,String ipAddr) { super(username, password, rememberMe, host); this.captcha = captcha; this.ipAddr=ipAddr; } public String getCaptcha() { return captcha; } public void setCaptcha(String captcha) { this.captcha = captcha; } public String getIpAddr() { return ipAddr; } public void setIpAddr(String ipAddr) { this.ipAddr = ipAddr; } }shiro登录认证调用有2种认证方式,个人理解为主动触发和被动触发,
主动触发是通过调用subject.login(token)方法如下:这种方式shiro 的/login=anon
@RequestMapping("tologin") public String login(Model model, HttpServletRequest request,HttpServletResponse response) throws Exception { System.out.println("login =======start=="); Subject subject = SecurityUtils.getSubject(); subject.login(token); System.out.println("login ======end==="); return "login"; }被动触发:是在shiro 的loginurl属性和登录表单的action跳转url 一致,get请求直接返回界面,post请求会调用认证 这种方式shiro 的/login=authc
@RequestMapping("login") public String login(Model model, HttpServletRequest request,HttpServletResponse response) throws Exception { System.out.println("login =======start=="); Subject subject = SecurityUtils.getSubject(); if (subject.isAuthenticated()) { // 已经登录,跳转到自己的首页 WebUtils.issueRedirect(request, response, "/getMyJsp"); return "login"; } System.out.println("login ======end==="); return "login"; }
问题小结:
shiro 登录后,样式不显示
可能原因,shiro的filter 把样式给拦截了,注意shiro自定义的filter 不能交给spring 管理,并且要注意拦截器的顺序,shiroFilter 在其他拦截器之前
shiro 报there is no session with id []
产生此原因可能是在代码中的某个地方调用了session.invalidate(),或者shiro 的logout方法,之后又使用了request,session的方法
shiro 点击登录,或者认证成功后继续点击,总是返回到登录页面
正常情况下如果认证失败会返回登录界面,如果认证通过了返回登录界面可以查看设置sessionManager 的setSessionIdCookie()是如何设置cookie的,尽量不要创建新的cookie 而是使用sessionManager.getSessionIdCookie()获取默认的cookie进行设置
相关文章推荐
- springboot整合shiro
- Springboot整合shiro 路径问题
- springboot thymeleaf和shiro 整合——按钮可见性
- springboot整合shiro
- spring boot 整合shiro 配置类报错问题
- Spring Boot整合shiro出现UnavailableSecurityManagerException
- Spring Boot+Shiro+Redis(redisson)整合时,采用内嵌tomcat启动错误原因分析
- SpringBoot整合mybatis、shiro、redis实现基于数据库的细粒度动态权限管理系统实例
- springboot(十四):springboot整合shiro-登录认证和权限管理
- Springboot + shiro 整合之Url拦截设置(转)
- springboot+shiro+redis(单机redis版)整合教程-续(添加动态角色权限控制)
- spring boot整合Shiro实现单点登录
- spring boot整合redis实现shiro的分布式session共享的方法
- springboot(十四):springboot整合shiro-登录认证和权限管理
- Spring Boot+Shiro+Redis(redisson)整合时,采用内嵌tomcat启动错误原因分析
- springboot 与 shiro 整合 (简洁版)
- springboot整合shiro登录失败次数限制功能的实现代码
- 快速搭建springboot框架以及整合ssm+shiro+安装Rabbitmq和Erlang、Mysql下载与配置
- springboot(十四):springboot整合shiro-登录认证和权限管理
- 解决SpringBoot整合shiro之后无法加载静态资源文件问题