shiro入门
1.shiro简单介绍
Apache shiro是一个简单易用的J2EE安全框架,它可用作项目中的认证,授权,加密,session管理等操作,先来几个概念的介绍
Authentication: 认证。即验证是哪个用户登录。
Authorization:也被称为访问控制,即决定当前登录用户是否有权限去访问受保护的资源。
Cryptography:通过加密算法保护数据安全。
Session Management: 当用户使用你的应用是自身携带的数据。
2.springMVC整合shiro的几个简单步骤
首先在web.xml中配置下shiro的过滤器,让shiro接受处理需要管理请求,一般来说这个项目的请求都配进去
<filter> <!-- 一般来说,shiro的过滤器应该放在其他所有过滤器的最前面,表示请求之前先让shiro处理,但是也不绝对 --> <!-- 此处的为shiro对应的过滤器名称,应该跟spring的application中的管理 shiro的org.apache.shiro.spring.web.ShiroFilterFactoryBean的id同名 --> <filter-name>shiroFilter</filter-name> <filter-class> org.springframework.web.filter.DelegatingFilterProxy </filter-class> <init-param> <param-name>targetFilterLifecycle</param-name> <!-- 此处缺省值为false,表示生命周期由SpringApplicationContext管理, 设置成true表示由ServletContainer管理 --> <param-value>true</param-value> </init-param> </filter> <filter-mapping> <filter-name>shiroFilter</filter-name> <!-- /*表示所有请求均需要shiro拦截处理 --> <url-pattern>/*</url-pattern> </filter-mapping>
下来进行spring的applicationContext.xml的配置
<!-- 这里主要是设置自定义的单Realm应用,若有多个Realm,可使用'realms'属性代替 --> <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager"> <property name="realm" ref="ShiroRealm" /> </bean> <!-- 項目自定义的Realm需要继承AuthorizingRealm 用来自定义shiroReal,即制定shiro验证用户登录的类为自定义的shiroReal --> <bean id="ShiroRealm" class="com.fh.interceptor.shiro.ShiroRealm" ></bean> <!-- Shiro主过滤器本身功能十分强大,其强大之处就在于它支持任何基于URL路径表达式的、自定义的过滤器的执行 --> <!-- Web应用中,Shiro可控制的Web请求必须经过Shiro主过滤器的拦截,Shiro对基于Spring的Web应用提供了完美的支持 --> <!-- 此处id应该跟web.xml中的过滤器名称同名 --> <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean"> <!-- 注入shiro的安全管理员 ,Shiro的核心安全接口,这个属性是必须的 --> <property name="securityManager" ref="securityManager" /> <!-- 注入登录路径 loginUrl :没有登录的用户请求需要登录的页面时自动跳转到登录页面,不是必须的属性, 不输入地址的话会自动寻找项目web项目的根目录下的”/login.jsp”页面,默认会自动寻找Web工程根目录下的"/login.jsp"页面 --> <property name="loginUrl" value="/" /> <!-- 注入登录成功的路径 successUrl :登录成功默认跳转页面,不配置则跳转至”/”。如果登陆前点击的一个需要登录的页面, 则在登录自动跳转到那个需要登录的页面。不跳转到此。--> <property name="successUrl" value="/index.jsp" /> <!-- 注入权限不足的路径unauthorizedUrl :没有权限默认跳转的页面。 --> <property name="unauthorizedUrl" value="/login_toLogin" /> <!-- url权限级别的控制 --> <!-- anon:匿名过滤,表示不需要任何权限即可访问--> <!-- authc:如果继续操作,需要做对应的表单验证否则不能通过--> <!-- logout:登录退出过滤器 --> <!-- roles:角色过滤器,判断当前用户是否指定角色 --> <property name="filterChainDefinitions"> <value> /static/login/** = anon /plugins/keypad/** = anon /static/js/myjs/** = authc /static/js/** = anon /uploadFiles/uploadImgs/** = anon /code.do = anon /login_login = anon /app**/** = anon /weixin/** = anon /** = authc </value> </property> </bean>
自定义realm的案例
此处代码借鉴自:http://www.cnblogs.com/rodge-run/p/6445963.html
public class BOSRealm extends AuthorizingRealm { @Resource private IUserDao userDao; //权限认证 @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken paramAuthenticationToken) throws AuthenticationException { UsernamePasswordToken token = (UsernamePasswordToken) paramAuthenticationToken; String username = token.getUsername(); //调用userdao根据用户名查询用户 User user = userDao.findByUsername(username); if (user != null) { //如果查询的用户存在 //TODO 与数据库中用户名和密码进行比对。比对成功则返回info,比对失败则抛出对应信息的异常AuthenticationException SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(user, user.getPassword(), this.getClass().getName()); return authenticationInfo; } else { //如果查询不到用户, 返回空, Shiro会抛出UnknownAccountException异常 return null; } } //授予权限 @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection paramPrincipalCollection) { //创建授权信息对象 SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo(); //根据当前用户查询数据库,获取其权限对象 //获取当前用户,由于shiro的过滤器在struts的过滤器之前执行,因此此时的用户还没有被封装到session中, //故获取当前用户在session中娶不到 /*Subject subject = SecurityUtils.getSubject(); User loginUser = (User) subject.getPrincipal();*/ User loginUser = (User) paramPrincipalCollection.getPrimaryPrincipal(); if (loginUser != null) { List<Function> list = null; //表示用户存在,调用roledao根据用户查询所有权限 if ("admin".equals(loginUser.getUsername())) { //如果是超级管理员,赋予所有权限 list = functionDao.findAll(); } else { //根据用户id查询所有权限 list = functionDao.findFunctionByUserId(loginUser.getId()); } if (list != null && list.size() > 0) { for (Function function : list) { //为用户授权 simpleAuthorizationInfo.addStringPermission(function.getCode()); } } return simpleAuthorizationInfo; } else { return null; } } }
另外,shiro还提供了大量的标签,有需要时再实践了