1.先建一个实体UserInfo(由浅入深的顺序):
public class UserInfo implements Serializable{
private Long userId;
private String userName;
private Integer userAge;
private String userAddress;
private String userAccount;
private String userPassword;
}
注意此处是省略了get/set方法
2.Controller层
@Controller
@RequestMapping("/shiro")
public class LoginController {
@RequestMapping("/login")
public String login(@RequestParam("username") String name,@RequestParam("password") String pass){
Subject subject = SecurityUtils.getSubject();
if(!subject.isAuthenticated()){
UsernamePasswordToken token = new UsernamePasswordToken(name,pass);
subject.login(token);//最终的login方法会被提交到realm中
}
//重定向到页面
return "redirect:/list.jsp";
}
}
3.自定义的realm认证方法:
从token里面获取用户数据
public class MyRealm2 extends AuthenticatingRealm{
/**
* 认证方法
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
// TODO Auto-generated method stub
//先把authenticationToken强转为UserNamePasswordToken
UsernamePasswordToken upToken = (UsernamePasswordToken)token;
//通过usernamePasswordToken获取用户名
String username= upToken.getUsername();
//开始比对数据库
UserInfo userInfo = new UserInfo(1L,"张三",22,"上海","zhangsan","zhangsan");
//判断是否需要抛出异常
if(username.equals(userInfo.getUserName())){
}else{
throw new UnknownAccountException("用户名不存在");
}
//根据自己的情况获取用户信息并返回AuthenticationInfo对象
//principal:用户信息
//传username或者整个user对象
//credentials:密码
ByteSource salt = ByteSource.Util.bytes(username);
String password = new SimpleHash("md5","zhangsan",salt,1024).toHex();
SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(username,password,salt,getName());
return info;
}
}
注意:这个步骤:String password = new SimpleHash("md5","zhangsan",salt,1024).toHex();是为了迎合配置文件里面对密码加密的,若配置文件没有配置加密密码,那么也不需要此步骤,否则会验证不通过
4.配置文件
4.1applicationContext.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">
<!-- 配置securityManager 管理器 -->
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
<!-- 缓存管理器 -->
<property name="cacheManager" ref="cacheManager"></property>
<!-- realm领域 -->
<property name="realm" ref="jdbcRealm"></property>
</bean>
<!-- cacheManager:配置缓存管理器 为了使项目更高的运行,弊端:如果用户的账号和密码放在了缓存中,无论在登录页面输入什么账号密码都可以登录,
所以,一旦账号和密码进入缓存了,就需要logout方法才能退出缓存了 -->
<bean id ="cacheManager" class="org.apache.shiro.cache.ehcache.EhCacheManager">
<!-- 两种配置缓存的方式 第一种:配置多个缓存所需要的配置信息 -->
<!-- 第二种:配置单个缓存,直接以属性的形式配置进cacheManager中 -->
<!-- 配置缓存:从hibernate源码中找到ehcache.xml copy到项目的根目录 -->
<property name="cacheManagerConfigFile" value="classpath:ehcache.xml" />
</bean>
<!-- 3.配置自定义的Realm,如果没有自定义,可以使用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的路径 -->
<bean id="jdbcRealm" class="cn.jzh.shiro.MyRealm2">
<!-- 如果需要使用加密政策 -->
<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>
<!-- 4.配置lifecycleBeanPostProcessor:生命周期 把shiro的生命周期托管给spring IOC容器进行处理
shiro的init方法和destroy方法都由spring来进行管理调用 -->
<bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor" />
<!-- 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的路径匹配顺序:遵循第一次匹配优先顺序(在没有通配符的情况下) 如果和通配符连用,则遵循覆盖原则 -->
<property name="filterChainDefinitions">
<value>
/login.jsp = anon
/shiro/login = anon
/** = authc
</value>
</property>
</bean>
</beans>
4.2缓存配置文件ehcache.xml
<ehcache>
<diskStore path="java.io.tmpdir" />
<cache name="authorizationCache" eternal="false"
timeToIdleSeconds="3600" timeToLiveSeconds="0" overflowToDisk="false"
statistics="true">
</cache>
<cache name="authenticationCache" eternal="false"
timeToIdleSeconds="3600" timeToLiveSeconds="0" overflowToDisk="false"
statistics="true">
</cache>
<cache name="shiro-activeSessionCache" eternal="false"
timeToIdleSeconds="3600" timeToLiveSeconds="0" overflowToDisk="false"
statistics="true">
</cache>
<defaultCache maxElementsInMemory="10000" eternal="false"
timeToIdleSeconds="120" timeToLiveSeconds="120" overflowToDisk="true" />
<cache name="sampleCache1" maxElementsInMemory="10000" eternal="false"
timeToIdleSeconds="300" timeToLiveSeconds="600" overflowToDisk="true" />
<cache name="sampleCache2" maxElementsInMemory="1000" eternal="true"
timeToIdleSeconds="0" timeToLiveSeconds="0" overflowToDisk="false" />
</ehcache>
4.3shiro-server.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: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="cn.jzh"></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>
4.4页面的web.xml配置文件
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1">
<display-name>shiro_demo_spring_2</display-name>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.htm</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath*:applicationContext.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<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>
<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>
5.页面文件
login.jsp
<body>
<h1>Login Page</h1>
<form action="shiro/login" method="get">
用户名:<input type="text" name="username"><br>
密 码:<input type="password" name="password"><br>
<input type="submit" value="提交">
</form>
</body>