官方网站:http://shiro.apache.org
相关参考博文:
我的配置内容如下:
<dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-core</artifactId> <version>1.2.2</version> </dependency> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-web</artifactId> <version>1.2.2</version> </dependency> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-aspectj</artifactId> <version>1.2.2</version> </dependency> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-spring</artifactId> <version>1.2.2</version> </dependency> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-ehcache</artifactId> <version>1.2.2</version> </dependency>
上面的jar思路很清晰,除了shiro-code.jar外,与什么框架结合,就加上什么样jar。
具体全部的maven配置文件可参考:http://shiro.apache.org/download.html
<!--配置过滤器让请求资源经过 Shiro 的过滤处理--> <filter> <filter-name>shiroFilter</filter-name> <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class> <init-param> <param-name>targetFilterLifecycle</param-name> <param-value>true</param-value> </init-param> </filter> <filter-mapping> <filter-name>shiroFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
2.applicationContext-shiro.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.2.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.2.xsd"
default-lazy-init="false">
<!-- 权限管理器 -->
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
<property name="realm" ref="shiroDbRealm" />
</bean>
<!--内部过滤器配置-->
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean"
depends-on="frameperms">
<!-- shiro的核心安全接口 -->
<property name="securityManager" ref="securityManager" />
<!-- 要求登录时的链接 -->
<property name="loginUrl" value="/login" />
<!-- 登陆成功后要跳转的连接 -->
<property name="successUrl" value="/index" />
<!-- 未授权时要跳转的连接 -->
<property name="unauthorizedUrl" value="/unauth" />
<!-- shiro连接约束配置 -->
<property name="filterChainDefinitions">
<value>
<!--静态资源直接通过-->
/js/** = anon
/css/** = anon
/images/** = anon
/unauth = anon
/getCaptcha=anon
/login = anon
/favicon.ico = anon
<!--必须存在用户-->
/index = user
/logout = logout
<!--必须存在用户-->
/menu/leftMenu=user
<!--必须存在用户-->
/**/ajax/** = user
<!--必须存在用户,所有的请求都要通过 frameperms 验证-->
/** = user,frameperms
</value>
</property>
<property name="filters">
<map>
<entry key="frameperms" value-ref="frameperms"></entry>
</map>
</property>
</bean> <!-- 保证实现了Shiro内部lifecycle函数的bean执行 --> <bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor" />
</beans>
其中shiroDbRealm为认证授权类。具体代码如下:
/** * 关于shiro的缓存,我在这里说下.<br/> * 可以禁用shiro的缓存,调用spring的缓存,这样就省去了缓存的整合.<br/> * 其他框架遇到缓存问题,同样的思路解决. * @author 9iu.org * */ //认证数据库存储 @Component("shiroDbRealm") public class ShiroDbRealm extends AuthorizingRealm { public Logger logger = Logger.getLogger(getClass()); @Resource IUserRoleMenuService userRoleMenuService; public static final String HASH_ALGORITHM = "MD5"; public static final int HASH_INTERATIONS = 1; private static final int SALT_SIZE = 8; public ShiroDbRealm() { // super.setAuthenticationCacheName(authenticationCacheName); } // 授权 @Override protected AuthorizationInfo doGetAuthorizationInfo( PrincipalCollection principalCollection) { ShiroUser shiroUser = (ShiroUser) principalCollection.getPrimaryPrincipal(); // String userId = (String) // principalCollection.fromRealm(getName()).iterator().next(); String userId = shiroUser.getId(); if(StringUtils.isBlank(userId)){ return null; } // 添加角色及权限信息 SimpleAuthorizationInfo sazi = new SimpleAuthorizationInfo(); try { sazi.addRoles(userRoleMenuService.getRolesAsString(userId)); sazi.addStringPermissions(userRoleMenuService.getPermissionsAsString(userId)); } catch (Exception e) { logger.error(e); } return sazi; } // 认证 protected AuthenticationInfo doGetAuthenticationInfo( AuthenticationToken token) throws AuthenticationException { UsernamePasswordToken upToken = (UsernamePasswordToken) token; /* String pwd = new String(upToken.getPassword()); if (StringUtils.isNotBlank(pwd)) { pwd = DigestUtils.md5Hex(pwd); } */ // 调用业务方法 User user = null; try { user = userRoleMenuService.findLoginUser(upToken.getUsername(), new String(upToken.getPassword())); } catch (Exception e) { logger.error(e); } if (user != null) { // 要放在作用域中的东西,请在这里进行操作 // SecurityUtils.getSubject().getSession().setAttribute("c_user", // user); // byte[] salt = EncodeUtils.decodeHex(user.getSalt()); return new SimpleAuthenticationInfo(new ShiroUser(user),user.getPassword(),getName()); } // 认证没有通过 return null; } /** * 设定Password校验的Hash算法与迭代次数. */ @PostConstruct public void initCredentialsMatcher() { HashedCredentialsMatcher matcher = new HashedCredentialsMatcher(HASH_ALGORITHM); matcher.setHashIterations(HASH_INTERATIONS); setCredentialsMatcher(matcher); }
配置文件中frameperms类,内容如下:
@Component("frameperms") public class FramePermissionsAuthorizationFilter extends PermissionsAuthorizationFilter { public Logger logger=Logger.getLogger(getClass()); @Resource private IMenuService menuService; @Override public boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) throws IOException { HttpServletRequest req = (HttpServletRequest) request; Subject subject = getSubject(request, response); String uri = req.getRequestURI(); String requestURL = req.getRequestURL().toString(); String contextPath = req.getContextPath(); if(uri.endsWith("/pre")){// 去掉pre uri=uri.substring(0,uri.length()-4); } int i=uri.indexOf(contextPath); if(i>-1){ uri=uri.substring(i+contextPath.length()); } if(StringUtils.isBlank(uri)){ uri="/"; } boolean permitted = subject.isPermitted(uri); String isqx="否"; if(permitted){ isqx="是"; } String ip = IPUtils.getClientAddress(req); Fwlog fwlog=new Fwlog(); fwlog.setFwUrl(requestURL); fwlog.setIsqx(isqx); fwlog.setIp(ip); Subject user = SecurityUtils.getSubject(); ShiroUser shiroUser = (ShiroUser) user.getPrincipals().getPrimaryPrincipal(); fwlog.setUserCode(shiroUser.getAccount()); fwlog.setUserName(shiroUser.getName()); Date startDate=new Date(); fwlog.setStartDate(startDate); fwlog.setStrDate(DateUtils.convertDate2String("yyyy-MM-dd HH:mm:ss.SSSS", startDate)); HttpSession httpSession = req.getSession(false); if(httpSession!=null){ fwlog.setSessionId(httpSession.getId()); } try { String menuName = menuService.getNameByPageurl(uri); fwlog.setMenuName(menuName); menuService.save(fwlog); } catch (Exception e) { logger.error(e); } return permitted; } }
@RequestMapping(value = "/login",method=RequestMethod.POST) public String loginPost(User currUser,HttpSession session,Model model,HttpServletRequest request) throws Exception { Subject user = SecurityUtils.getSubject(); String code = (String) session.getAttribute(GlobalStatic.DEFAULT_CAPTCHA_PARAM); if(StringUtils.isNotBlank(code)){ code=code.toLowerCase().toString(); } String submitCode = WebUtils.getCleanParam(request, GlobalStatic.DEFAULT_CAPTCHA_PARAM); if(StringUtils.isNotBlank(submitCode)){ submitCode=submitCode.toLowerCase().toString(); } if (StringUtils.isBlank(submitCode) ||StringUtils.isBlank(code)||!code.equals(submitCode)) { model.addAttribute("message", "验证码错误!"); return "/login"; } UsernamePasswordToken token = new UsernamePasswordToken(currUser.getAccount(),currUser.getPassword()); token.setRememberMe(true); try{ user.login(token); }catch(IncorrectCredentialsException e){ model.addAttribute("message", "账号或密码错误"); return "/login"; }catch(Exception e){ model.addAttribute("message", "账号或密码错误"); return "/login"; } return "redirect:/index"; }