shiro安全控制目录
1. 导入依赖
<properties>
<shiro.version>1.2.3</shiro.version>
</properties>
<dependencies>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-core</artifactId>
<version>${shiro.version}</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-web</artifactId>
<version>${shiro.version}</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>${shiro.version}</version>
</dependency>
</dependencies>
2. web.xml配置
在web.xml中,将拦截器交由Spring管理。shiro(3)-Filter交由Spring管理-DelegatingFilterProxy。
<?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"
version="3.0">
<display-name>helloworld</display-name>
<!-- 读取spring配置文件 -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
classpath:/spring/applicationContext.xml,
classpath:/spring/application-shiro.xml,
classpath:/spring/spring-mybatis.xml
</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!--拦截器由spring容器管理-->
<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>
<!-- springMVC核心配置 -->
<servlet>
<servlet-name>dispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:/spring/spring-mvc.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<!-- 拦截设置 -->
<servlet-mapping>
<servlet-name>dispatcherServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
注:设置targetFilterLifecycle=true的含义是保留Filter原有的init和destory方法的调用。
3. Spring配置文件
3.1 配置详解
3.1.1. shiro主过滤器
[费有特][陈][带神你神子]
常用的权限控制:
- anno:任何人都可以访问;
- authc:必须登录之后才能访问,不包括remember me(记住密码);
- user:登录用户才可以访问,包含remember me(记住密码);
- perm:过滤[权限]规则,这个一般扩展使用(使用自定义过滤器,从数据库查询用户权限),不会使用原生的。
- roles:过滤[角色]规则,这个一般扩展使用,不会使用原生的。
拦截器优先级:
从上到下,从左到右,如果有匹配的拦截器就会阻断并返回,例如访问js/a.js,第一个拦截器anon符合,就返回true了,不在往下进行匹配了。注意最后一个拦截最后一句是 /**=user意思就是除了上面的那些,其他的所有都要经过。
<!-- Shiro主过滤器本身功能十分强大,其强大之处就在于它支持任何基于URL路径表达式的、自定义的过滤器的执行 -->
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
<!--shiro的核心安全接口,这是属性是必须的-->
<property name="securityManager" ref="securityManager"/>
<!-- 要求登录时的链接,非必须的属性,默认会自动寻找Web工程根目录下的"/login.jsp"页面 -->
<property name="loginUrl" value="/login/init"></property>
<!-- 用户访问未对其授权的资源时,所显示的连接 -->
<property name="unauthorizedUrl" value="/pages/error/403.jsp"/>
<!--定义过滤器链-->
<property name="filterChainDefinitions">
<value>
<!--Shiro过滤器链的配置-->
/login/init/** = anon <!-- 对于登录相关不进行鉴权 -->
/static/** = anon <!-- 静态资源不进行鉴权 -->
/** = user
</value>
</property>
<property name="filters">
<map>
<entry key="user" value-ref="userFilter"></entry>
</map>
</property>
</bean>
<!--自定义拦截器-->
<bean id="userFilter" class="com.springmvc.common.filter.SystemUserFilter"/>
3.1.2. 配置securityManager
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
<!--作用:授权认证,此处为单个realm,若想配置多个,可使用realms参数-->
<property name="realm" ref="myRealm"/>
<!--设置会话模式(已过期),需配置适当的WebSessionManager实例-->
<property name="sessionMode" value="http"/>
<!--建议关闭,配合/**=user使用时,可未经授权登录系统-->
<property name="rememberMeManager" ref="rememberMeManager"/>
<!--配置会话管理器-->
<property name="sessionManager" ref="defaultWebSessionManager"/>
</bean>
DefaultWebSecurityManager类主要定义了设置subjectDao,获取会话模式,设置会话模式,设置会话管理器,是否http会话模式等操作。
3.1.3 配置remeberManager
java shiro配置记住密码功能 RememberMe功能怎么实现
Shiro的 rememberMe 功能使用指导(为什么rememberMe设置了没作用?)
<!-- remenberMe配置 -->
<bean id="rememberMeCookie" class="org.apache.shiro.web.servlet.SimpleCookie">
<constructor-arg value="rememberMe" />
<!-- 浏览器中通过document.cookie可以获取cookie属性,设置了HttpOnly=true,在脚本中就不能的到cookie,可以避免cookie被盗用 -->
<property name="httpOnly" value="true" />
<!-- 默认记住7天(单位:秒) -->
<property name="maxAge" value="604800" />
</bean>
<!-- rememberMe管理器 -->
<bean id="rememberMeManager" class="org.apache.shiro.web.mgt.CookieRememberMeManager">
<property name="cipherKey" value="#{T(org.apache.shiro.codec.Base64).decode('4AvVhmFLUs0KTA3Kprsdag==')}" />
<property name="cookie" ref="rememberMeCookie" />
</bean>
注:Shiro主过滤器要使用/** = user。
3.1.4Realm配置
AuthorizingRealm为自定义Realm的父类,该类采用的模板方法模式,提供了2个方法供我们实现。
shiro(5)-有状态认证-Realm认证的实现
- Authentication
[噢繁体kei神]
认证; - Authorization
[额死乱贼神]
授权;
<bean id="myRealm" class="com.springmvc.common.shiro.UserAuthorizingRealm"></bean>
3.1.5 sessionManager配置
DefaultWebSessionManager类主要定义了session的创建,启动,暂停与cookie的关联定义。
<bean id="defaultWebSessionManager" class="org.apache.shiro.web.session.mgt.DefaultWebSessionManager">
<!--全局session过期时间:30分钟操作会覆盖web.xml文件中的超时时间配置 -->
<property name="globalSessionTimeout" value="1800000"/>
<!---session保存到redis中-->
<property name="sessionDAO" ref="customShiroSessionDAO"/>
<!-- 所有的session一定要将id设置到Cookie之中,需要提供有Cookie的操作模版 -->
<property name="sessionIdCookie" ref="simpleCookie"/>
<!--定时扫描超时session-->
<!-- session 监听,可以多个。 -->
<property name="sessionListeners">
<list>
<ref bean="customSessionListener"/>
</list>
</property>
<!--session关闭调度器-->
<property name="sessionValidationScheduler" ref="sessionValidationScheduler"/>
<!-- 需要让此session可以使用该定时调度器进行检测 -->
<property name="sessionValidationSchedulerEnabled" value="true"/>
<!--删除过期的session-->
<property name="deleteInvalidSessions" value="true"/>
</bean>
<!--自定义cookie的SessionId-->
<bean id="simpleCookie" class="org.apache.shiro.web.servlet.SimpleCookie">
<constructor-arg index="0" value="JSESSIONID_COOKIE"/>
<property name="httpOnly" value="true"/>
</bean>
<!--自定义session监听器-->
<bean id="customSessionListener" class="om.springmvc.common.filter.CustomSessionListener">
<property name="shiroSessionRepository" ref="jedisShiroSessionRepository"/>
</bean>
自定义sessionListener:
public class CustomSessionListener implements SessionListener {
public void onStart(Session session) {
}
public void onStop(Session session) {
}
public void onExpiration(Session session) {
}
}
3. 代码中的使用
@Controller
@RequestMapping("/login")
public class LoginAction {
@RequestMapping(value = {"/init"})
public ModelAndView init() {
ModelAndView mv = new ModelAndView("login");
return mv;
}
@RequestMapping("/login")
public String login(@Param("username") String username,@Param("password") String password) {
try {
//创建token
UsernamePasswordToken token = new UsernamePasswordToken();
token.setUsername(username);
token.setPassword(password.toCharArray());
token.setRememberMe(true);
//调用验证
Subject subject = SecurityUtils.getSubject();
subject.login(token);
//验证是否登录
if(subject.isAuthenticated()){
Session session=subject.getSession();
//整合redis设置session超时时间setex(sessionId,30*60);
//返回到页面
return "redirect:/user";
}
} catch (UnknownAccountException e) {
//无用户名
}catch (LockedAccountException e){
//密码没找到
}catch (IncorrectCredentialsException e){
//密码不匹配
}catch (AuthenticationException e){
//其他登录错误
}catch (Exception e){
//未知异常
}
return "/error/403";
}
}