shiro-入门,快速与springmvc整合,全注解,最简单让项目运行起来
来源:互联网 发布:在线域名生成器短链接 编辑:程序博客网 时间:2024/05/29 18:09
笔记:springboot、springmvc全注解入门整合shiro
功能介绍
2015-11-19注 :最近看了架构探险中对shiro的讲解,下面这篇文章,在使用的方式上是正确的,有一些配置和使用至于是为什么,则需要你们自己去看架构探险章节的说明了,时隔一年来看这篇文章还是觉得很有价值,在当时也只会用使用能满足自己的要求。
本文的认证方法处理有误,正确的应该是:login提交用户表单提交的用户名和密码,doGetAuthenticationInfo认证方法里面放置正确的用户名和密码,让框架去匹配是否通过认证,以抛出异常的方式进行通知调用处没有通过认证,session中不会存放该用户的信息。
该示例:大概功能如下:
由于角色可以自由创建,拥有权限分配的功能的帐号,可以把自身的权限分配给创建的角色。所以本人只想到了,使用请求地址来控制每一个权限。
整合开始:
1.添加shiroFilter过滤器
在能替代web.xml的配置类中添加过滤器
/** * 用注解方式,类里面配置,完全取代 web.xml中的配置 * @author admin */@Order(1) //第一启动顺序@HandlesTypes(WebApplicationInitializer.class) //可能是标识这个是一个web上下文初始化的类(在springboot中该类需要在WebMvcConfigurerAdapter(可自定义继承该类)中加载调用)public class WebXml implements ServletContextInitializer { Logger logger = LoggerFactory.getLogger(getClass()); @Override public void onStartup(ServletContext servletContext) throws ServletException { logger.info("加载shiro过滤器,与spring集成"); /** * 找名字为shiroFilter(filter-name)的bean 并把所有Filter的操作委托给它。然后将ShiroFilter * 配置到spring容器即可 */ Dynamic shiroFilter = servletContext.addFilter("shiroFilter", DelegatingFilterProxy.class); shiroFilter.setInitParameter("argetFilterLifecycl", "true"); shiroFilter.addMappingForUrlPatterns(EnumSet.of(DispatcherType.REQUEST), false, "/*"); shiroFilter.setAsyncSupported(true); }}
2.配置WebMvcConfigurer
下面的类中有点多,但是指需要添加与shiro先关的几个bean就成了。
之前的是在项目中配置好的
public class WebConfig extends WebMvcConfigurerAdapter { Logger logger = LoggerFactory.getLogger(getClass()); @Bean public ServletContextInitializer getMyFilter() { logger.info("注册web.xml中对应的配置都可以在这里类里面编写-----------"); return new WebXml(); } /** * 添加全局异常处理器 1:这里好像是不用屏蔽 springmvc自动注册的全局异常处理器 2:编写自定义处理器 实现 * HandlerExceptionResolver 3:在这里加载 * */ @Bean public HandlerExceptionResolver getHandlerExceptionResolver() { logger.info("加载自定义异常处理器"); return new ExceptionResolverCustom(); } @Override public void addInterceptors(InterceptorRegistry registry) { logger.info("自定义拦截器在这里增加"); registry.addInterceptor(new LoginInterceptor()); super.addInterceptors(registry); } /* * @Bean public InternalResourceViewResolver * getInternalResourceViewResolver() { logger.info("加载视图解析器,配置springmvc的视图解析器,一般用于jsp开发?"); * InternalResourceViewResolver resolver = new * InternalResourceViewResolver(); resolver.setSuffix(".html"); return * resolver; } */ @Bean public EmbeddedServletContainerCustomizer containerCustomizer() { logger.info("加载错误页面相关处理,spring boot中可以对根据对应的状态码,比如404,等添加指定的页面"); return new MyCustomizer(); }//会话ID生成器 @Bean public SessionIdGenerator sessionIdGenerator() { JavaUuidSessionIdGenerator jusg = new JavaUuidSessionIdGenerator(); return jusg; }// <!-- 会话DAO,用来方便的获得 当前用户的session,也就是说,在任何一个普通类里面都可以使用Subject subject = SecurityUtils.getSubject(); Session session = subject.getSession(); 这个代码来获取当前用户的session --> @Bean public EnterpriseCacheSessionDAO sessionDao() { EnterpriseCacheSessionDAO ecd = new EnterpriseCacheSessionDAO(); ecd.setSessionIdGenerator(this.sessionIdGenerator()); ecd.setCacheManager(this.shiroCacheManager()); return ecd; } private EhCacheManager ec = null; //缓存,这个缓存,没有集成成功。 @Bean public EhCacheManager shiroCacheManager() { if(ec == null) { ec = new EhCacheManager(); ec.setCacheManagerConfigFile("classpath:ehcache-shiro.xml"); } return ec; } //会话管理器 @Bean public SessionManager sessionManager() { DefaultWebSessionManager dwsm = new DefaultWebSessionManager(); dwsm.setGlobalSessionTimeout(1800000); // 超时 dwsm.setDeleteInvalidSessions(true);// dwsm.setSessionValidationSchedulerEnabled(true);// dwsm.setSessionValidationScheduler(this.);// dwsm.setCacheManager(this.shiroCacheManager()); dwsm.setSessionDAO(this.sessionDao()); return dwsm; } //安全管理器 @Bean public SecurityManager securityManager() { UserRealm singleRealm = new UserRealm(); singleRealm.setAuthorizationCachingEnabled(true); DefaultWebSecurityManager dwsm = new DefaultWebSecurityManager(singleRealm); //加载自定义realm域 dwsm.setSessionManager(this.sessionManager()); return dwsm; } //<!-- 相当于调用SecurityUtils.setSecurityManager(securityManager) --> @Bean public MethodInvokingFactoryBean methodInvokingFactoryBean() { MethodInvokingFactoryBean mifb = new MethodInvokingFactoryBean(); mifb.setStaticMethod("org.apache.shiro.SecurityUtils.setSecurityManager"); mifb.setArguments(new Object[] {this.securityManager()}); return mifb; } //web过滤器 @Bean(name="shiroFilter") public ShiroFilterFactoryBean shiroFilterFactoryBean () { ShiroFilterFactoryBean sffb = new ShiroFilterFactoryBean(); sffb.setSecurityManager(this.securityManager()); sffb.setLoginUrl("/login.html");//设置登录页面 sffb.setUnauthorizedUrl("/unAuthc.html"); //未授权跳转的页面 Map<String, Filter> filters = new HashMap<>(); filters.put("sysUser", new SysUserFilter()); //自定义过滤器,我是用它来拦截自定义的权限监测调用 sffb.setFilters(filters); //设置对应的url对应的过滤链 Map<String, String> filterChainDefinitionMap = new LinkedHashMap<String, String>(); filterChainDefinitionMap.put("/login.html", "anon"); filterChainDefinitionMap.put("/system/login/login", "anon"); filterChainDefinitionMap.put("/system/login/logOut", "anon"); filterChainDefinitionMap.put("/errorCustom.html", "anon"); filterChainDefinitionMap.put("/unAuthc.html", "anon"); filterChainDefinitionMap.put("/views/app.js", "anon"); filterChainDefinitionMap.put("/js/**", "anon"); filterChainDefinitionMap.put("/", "anon"); filterChainDefinitionMap.put("/images/**", "anon"); filterChainDefinitionMap.put("/imag/**", "anon"); filterChainDefinitionMap.put("/wxMessagePic/*", "anon"); filterChainDefinitionMap.put("/css/**", "anon"); filterChainDefinitionMap.put("/**", "sysUser");//可以看到对于一些公共的地址我进行了放行,对于/**使用了自定义的过滤器进行处理,意思就是说:除了以上放行的地址,其他的地址都会被调用自定义的过滤器方法中 sffb.setFilterChainDefinitionMap(filterChainDefinitionMap); return sffb; } //shiro 生命周期处理器 @Bean public LifecycleBeanPostProcessor LifecycleBeanPostProcessor() { return new LifecycleBeanPostProcessor(); }}
3.编写自定义UserRealm
获取spring容器思路:12
import org.apache.shiro.realm.AuthorizingRealm;public class UserRealm extends AuthorizingRealm { /** * 获取授权信息,用户所拥有的角色和权限 */ @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) { //这里能得到这个参数,就是在下面的doGetAuthenticationInfo返回的用户验证信息。(这个是单realm的实现,直接调用这个方法,就能获得自定义的对象了) ShiroPrincipal shiroPrincipal = (ShiroPrincipal) principals.getPrimaryPrincipal(); Set<String> psIds = null; if (shiroPrincipal.isAuthorized()) { psIds = shiroPrincipal.getAuthorities(); } else { ISecurityService iss = Config.webApplicationContext.getBean(ISecurityService.class); try { psIds = iss.findByUsername(shiroPrincipal.getUsername()); shiroPrincipal.setAuthorized(true); } catch (Exception e) { e.printStackTrace(); } } SimpleAuthorizationInfo si = new SimpleAuthorizationInfo(); si.setStringPermissions(psIds); // setRoles 暂时只实现权限判断 return si; } /** * 获取身份验证相关信 */ @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { //这个token,是在登录方法里面,调用login方法,把用户名和密码传递过来的 //Subject subject = SecurityUtils.getSubject(); //subject.login(new UsernamePasswordToken(systemVo.getUsername(), systemVo.getPassword())); String username = (String) token.getPrincipal(); // 得到用户名 String password = new String((char[]) token.getCredentials()); // 得到密码 // 如果身份认证验证成功,返回一个AuthenticationInfo实现 // 这里处理的流程:暂时是,先通过了系统的自定义流程之后,再调用shiro的login功能,跳转到这里,所以 // 就不用去获取用户等数据了。直接返回对象:简单的对象实体 new SimpleAuthenticationInfo(username, // password, getName()); // 第一个参数,可以在授权方法中获取到 ShiroPrincipal principal = new ShiroPrincipal(username); return new SimpleAuthenticationInfo(principal, password, this.getName()); }}
4.编写自定义过滤器
import org.apache.shiro.SecurityUtils;import org.apache.shiro.subject.Subject;import org.apache.shiro.web.filter.PathMatchingFilter;public class SysUserFilter extends PathMatchingFilter { @Override protected boolean onPreHandle(ServletRequest request, ServletResponse response, Object mappedValue) throws Exception { HttpServletRequest req = (HttpServletRequest) request; HttpServletResponse res = (HttpServletResponse) response; String url = req.getRequestURI();// 用户请求的地址 Subject subject = SecurityUtils.getSubject(); String username = (String)subject.getPrincipal(); if("superadmin".equals(username)) { //系统超级管理员放行 return true; } Integer rulKey = this.matchingURL(url); if(subject.isPermitted(rulKey+"")) { //如果有权限。则放行 return true; }else { String method = req.getMethod(); String header = req.getHeader("Accept"); if(header.startsWith("application/json")) { JSONObject responseJSONObject = new JSONObject(); responseJSONObject.put("0", "你没有该权限"); res.setContentType("application/json; charset=utf-8"); res.setCharacterEncoding("UTF-8"); PrintWriter out = null; out = res.getWriter(); out.append(responseJSONObject.toString()); } } res.sendRedirect("/unAuthc.html"); return false; } /** * * @Title: matchingURL * @Description:根据当前请求地址获取标准的公共权限地址,只要是正常的访问。就应该能和公共权限中 一一对应查找到 * @param currentUrl * @return Integer 获取到后,返回该公共地址的权限id,返回null,则表示请求的资源在公共权限库中没有找到(待定义处理) * @version V0.1 * @createDate 2015年3月18日 下午4:00:40 * @updateDate 2015年3月18日 下午4:00:40 */ private Integer matchingURL(String currentUrl) { Map<Integer, String> authUrls = StaticCache.authUrls; for (Map.Entry<Integer, String> url : authUrls.entrySet()) { if(currentUrl.contains(url.getValue())) { //匹配上 return url.getKey(); } } return null; }}
5.总结
用一张图来表示,shiro大概的入门调用流程,这个是自己花了一天时间理解的。也不知道对不对。反正就先这样用着先。
总结步骤:
1.添加shiro过滤器入口(一定要保证白过滤器在其他过滤器之前,至少在配置清单中在最前面)
2:配置安全管理器,设置自定义realm
3:配置web过滤器(也就是定义shiroFilter,定义的入口会搜寻该对象),设置权限,设置自定义过滤器拦截权限处理
- 我是专门做了一个监听器,在监听器中利用servletcontext来获取到spring的容易,然后存入一个工具类中的静态常量中。也就是说这样操作之后,在一个普通的java类中也可以获得spring容器 ↩
- 用一个工具类实现spring的接口,然后用spring容器初始化该工具类,就能获取容器了 ↩
0 0
- shiro-入门,快速与springmvc整合,全注解,最简单让项目运行起来
- SpringMVC与Shiro的最简单整合(不包含权限管理)
- shiro与springMVC整合
- Shiro学习--与SpringMVC整合(数据库,Shiro注解和Shiro标签)
- Shiro学习--与SpringMVC整合(数据库,Shiro注解和Shiro标签)
- Shiro学习--与SpringMVC整合(数据库,Shiro注解和Shiro标签)
- SpringMVC+Hibernate全注解整合
- Shiro第四篇【Shiro与Spring整合、快速入门、Shiro过滤器、登陆认证】
- SpringMVC与shiro的整合
- shiro与springMVC的整合
- SpringMVC与shiro的整合
- Redis入门很简单之九【SpringMvc+Mybatis与redis整合让Mybatis管理缓存】
- shiro与spring整合详解与spring项目中shiro注解不生效的解决办法
- Shiro入门-shiro与spring整合
- shiro简单理解及整合springMVC
- springmvc 整合shiro ehcache 项目源码
- shiro与SSM项目整合
- shiro与SSM项目整合
- 蓝桥杯数字游戏
- Rails小知识点积累之一
- 破解TD OA
- Sicily 1343. Jam的计数法
- javascript开发调试
- shiro-入门,快速与springmvc整合,全注解,最简单让项目运行起来
- 判断cpu大小端
- Sicily 1336. Power Mean
- javascript中正则表达式和ruby中的一点差异
- 蓝桥杯算法训练之道路和航路 (邻接表SPFA+SLF优化)
- TPC-H
- PHP笔记--数据库操作
- Sicily 1310. Right-Heavy Tree
- Bootstrap-CSS-代码