shiro ,三大块。
前期准备ehcache.xml,以及mvc以及shiro和shiro-spring等等的jar包,
然后开始配置
第一块 web.xmlddddddd
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>
<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>
<!-- <init-param>
<param-name>targetBeanName</param-name>
<param-value>shiroFilter</param-value>
</init-param> -->
</filter>
<filter-mapping>
<filter-name>shiroFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<listener> //配置监听
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet>
<servlet-name>shiro</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>shiro</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
第二块 shiro-servlet.xml (不同的人可以起不同的名字,他的位置在web-inf下面,)
<?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:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">
<context:component-scan base-package="com.zzsxt.lee.web.shiro"></context:component-scan>
<bean //配置视图解析器
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/"></property>
<property name="suffix" value=".jsp"></property>
</bean>
<mvc:annotation-driven></mvc:annotation-driven>
<mvc:default-servlet-handler />
</beans>
第三块:applicationContext.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"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<!-- ========================================================= Shiro Core
Components - Not Spring Specific ========================================================= -->
<!-- 1.配置securityManager:安全管理器 -->
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
<!-- 缓存管理器 -->
<property name="cacheManager" ref="cacheManager" />
<!-- !!!!!!!realm -->
<property name="realm" ref="jdbcRealm" />
</bean>
<!-- 2.cacheManager:配置缓存管理器 为了使项目更高效的运行 弊端:如果用户的账号和密码放在缓存中,无论在登录页面舒服什么账号和密码都可以直接登录
所以一旦账号和密码存入缓存中了,需要直接退出(logout) -->
<bean id="cacheManager" class="org.apache.shiro.cache.ehcache.EhCacheManager">
<!-- 两种配置缓存的方式 第一种:配置多个缓存所需要的配置信息 -->
<!-- Set a net.sf.ehcache.CacheManager instance here if you already have
one. If not, a new one will be creaed with a default config: <property name="cacheManager"
ref="ehCacheManager"/> -->
<!-- 第二种:配置单个缓存,直接以属性的形式配置进cacheManager中 -->
<!-- If you don't have a pre-built net.sf.ehcache.CacheManager instance
to inject, but you want a specific Ehcache configuration to be used, specify
that here. If you don't, a default will be used.: <property name="cacheManagerConfigFile"
value="classpath:some/path/to/ehcache.xml"/> -->
<!-- 配置缓存:从hibernate源码中找到ehcache.xml copy到项目的根目录 -->
<property name="cacheManagerConfigFile" value="classpath:ehcache.xml" />
</bean>
<!-- 3. m,如果没有自定义,可以使用shiro自带的默认Reaml(在真实开发环境中,不允许使用) Many other
realm implementations can be used too:其他很多的org.apache.shiro.realm.Realm的实现类也可以被使用
3.1.创建Java类,不允许叫Realm,实现org.apache.shiro.realm.Realm的接口 3.2.修改class的路径 -->
<!-- Used by the SecurityManager to access security data (users, roles,
etc). Many other realm implementations can be used too (PropertiesRealm,
LdapRealm, etc. -->
<bean id="jdbcRealm" class="com.zzsxt.lee.web.shiro.MyRealm3">
<!-- 如果需要使用加密政策 -->
<property name="credentialsMatcher">
<bean class="org.apache.shiro.authc.credential.HashedCredentialsMatcher">
<property name="hashAlgorithmName" value="MD5"></property><!-- 指定加密的方式:MD5 -->
<property name="hashIterations" value="1024"></property><!-- 指定了加密的次数 -->
</bean>
</property>
</bean>
<!-- ========================================================= Shiro Spring-specific
integration ========================================================= -->
<!-- Post processor that automatically invokes init() and destroy() methods
for Spring-configured Shiro objects so you don't have to 1) specify an init-method
and destroy-method attributes for every bean definition and 2) even know
which Shiro objects require these methods to be called. -->
<!-- 4.配置lifecycleBeanPostProcessor:生命周期 把shiro的生命周期托管给spring IOC容器进行处理
shiro的init方法和destroy方法都由spring来进行管理调用 -->
<bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor" />
<!-- Enable Shiro Annotations for Spring-configured beans. Only run after
the lifecycleBeanProcessor has run: -->
<!-- 5.配置org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator
开启shiro自己的注解 DefaultAdvisorAutoProxyCreator必须要配置在lifecycleBeanPostProcessor之后 -->
<bean
class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"
depends-on="lifecycleBeanPostProcessor" />
<bean
class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">
<property name="securityManager" ref="securityManager" />
</bean>
<!-- 6.shiro的核心配置 6.1.配置shiroFilter:过滤器,进行过滤指定路径信息 第一种配置:shiro配置id为shiroFilter必须要和web.xml中<filter-name>一致
第二种配置: <filter> <init-param> <param-name>targetBeanName</param-name> <param-value>shiroFilter123</param-value>
</init-param> </filter> 通常情况下,第二种配置是不会被使用的 如果对不上 则抛出org.springframework.beans.factory.NoSuchBeanDefinitionException:
No bean named 'shiroFilter' is defined -->
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
<property name="securityManager" ref="securityManager" />
<!-- 登录的路径 -->
<property name="loginUrl" value="/login.jsp" />
<!-- 登录成功所需要跳转的路径,一般情况下由controller进行配置,所以这一个配置信息可以不要 -->
<property name="successUrl" value="/index.jsp" />
<!-- 没有权限的页面 -->
<property name="unauthorizedUrl" value="/unauthorized.jsp" />
<!-- 配置权限信息: anon:允许匿名访问,也就是这个路径不需要进行认证(登录) authc:必须认证(登录)后才可以访问的路径 通配符:
*:/test/* 在test的下一级目录/test/a允许访问 /test/a/a/不允许访问 **:/test/** 所有的子目录都可以访问
shiro的路径匹配顺序:遵循第一次匹配优先顺序(在没有通配符的情况下) 如果和通配符连用,则遵循覆盖原则
logout:退出登录
roles:判断该用户是否有该角色
如果在roles标签中的[]里配置了两个角色,这两个角色是并集的关系
-->
<property name="filterChainDefinitions">
<value>
/login.jsp = anon
/shiro/login = anon
/logout = logout
/shiro/test = anon
<!-- /user.jsp = roles[user]
/admin.jsp = roles[user,admin] -->
/** = authc
</value>
</property>
</bean>
<bean id="loginService" class="com.zzsxt.lee.web.shiro.service.LoginService"></bean>
</beans>
以上这些都是配置,下面是真正的代码
在applicationContext。xml里面的第6步,进行一些拦截,
/login.jsp = anon
/shiro/login = anon
这两个是对外开放的, 即 不需要任何权限就可以看到,也不会被拦截。
在controller层,需要对登录的用户进行判断,---会到appliactionContext.xml里面找
第3步 "jdbcRealm",对密码进行加密,这里,最好用自己定义的realm,如下
package com.zzsxt.lee.web.shiro;
import java.util.HashSet;
import java.util.Set;
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.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import com.zzsxt.lee.web.shiro.model.User;
/**
* @description shiro��֤����Ȩ shiro���հ汾 1.�̳�org.apache.shiro.realm.AuthorizingRealm
* 2.��д�������� ��֤doGetAuthenticationInfo() ��ȨdoGetAuthorizationInfo()
* ʵ����Ȩ��
* ͨ�������ļ�(applicationContext.xml)�ҵ�bean��idΪfilterChainDefinitions
* ���shiro��Ȩ�ޱ�ǩ
* ͨ��jstl��ǩ����ʵ��shiroȨ���ж�
* @author Seven Lee
*
*/
public class MyRealm3 extends AuthorizingRealm {
/**
* @description ��֤
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
// 1.从controller层传来的token,将其强转,
UsernamePasswordToken uptoken = (UsernamePasswordToken) token;
// 2.ͨ通过token获取用户名
String username = uptoken.getUsername();
// 3.
User user = new User("zhangsan", "2a0d136ceacafe198ea64ac09daaf1b6", "male");
// 4.�ж��Ƿ���Ҫ�׳��쳣
if (username.equals(user.getUsername())) {
} else {
throw new UnknownAccountException("�û���������");
}
// 5.�����Լ��������ȡ�û���Ϣ������AuthenticationInfo����
// principal:�û���Ϣ
// ��username�����ߴ�����User����
// credentials:����
// SimpleAuthenticationInfo info = new
// SimpleAuthenticationInfo(username, "123456", getName());
// credentialsSalt:��ֵ
ByteSource salt = ByteSource.Util.bytes(username);
SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(username, user.getPassword(), salt, getName());
return info;
}
/**
* @description ��Ȩ
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection colletion) {
/**
* PrincipalCollection:是从认证阶段返回的SimpleAuthenticationInfo对象
* 如果在认证阶段,返回是username,则授权阶段可以获取到username
* 如果在认证阶段,返回的是User对象,授权阶段可以获取该User对象
*/
// 1.ͨ通过PrincipalCollection获取username
String username = (String) colletion.getPrimaryPrincipal();
// 2.ͨ通过获取到username查询数据库,查看该user所对应的roles
Set<String> roles = new HashSet<String>();
// 3.ͨ通过username获取该角色下的权限
Set<String> permissions = new HashSet<String>();
roles.add("user");
if("admin".equals(username)) {
// 如果登陆者满足某种条件,则让其拥有admin权限,并且添加delete权限
roles.add("admin");
permissions.add("user:delete");
}
permissions.add("user:look");
// 4.创建AuthorizationInfo对象
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
// 5.把角色信息添加AuthorizationInfo对象
info.addRoles(roles);
// 6.把权限信息添加到AuthorizationInfo对象
info.addStringPermissions(permissions);
// 7.返回SimpleAuthorizationInfo对象
return info;
}
}
上面第一个方法是对用户的登录认证,下一个方法是对用户的授权
完成之后,会回到controller,进行跳转页面,这时,用户已经拥有了自己应该拥有的权限,然后会有两种方法对用户的权限进行判断,
一个是在applicationcontext.xml的第六步,进行判断,
如:/user.jsp = roles[user],这是说明,user拥有看user.jsp 页面的权利
/admin.jsp = roles[user,admin] ,这是说明,用户需要有“user”和“admin”l两种身份才能访问
另一种实在页面加入shiro标签,然后进行判断
可以是这种简单的判断,(判断是否是某类用户,就可以看到某个链接或者按钮)
<shiro:hasRole name="admin">
<a href="admin.jsp">Admin Page</a>
</shiro:hasRole>
也可以是下面这种,不仅对用户进行判断,还要对其权限进行判断否则
<shiro:hasRole name="user">
<shiro:hasPermission name="user:look">
<a href="user.jsp">User Page</a>
</shiro:hasPermission>
</shiro:hasRole>
这些都是雏形,以后更新应用版