1、web.xml中配置:
- <filter>
- <filter-name>shiroFilter</filter-name>
- <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
- <async-supported>true</async-supported>
- <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、shiro-spring.xml:
- <!-- Shiro的Web过滤器 -->
- <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
- <property name="securityManager" ref="securityManager"/>
- <property name="loginUrl" value="/login.jsp"/>
- <property name="unauthorizedUrl" value="/unauthorized.jsp"/>
- <property name="filters">
- <util:map>
- <entry key="authc" value-ref="formAuthenticationFilter"/>
- </util:map>
- </property>
- <property name="filterChainDefinitions">
- <value>
- /index.jsp = anon
- /unauthorized.jsp = anon
- /login.jsp = authc
- /logout = logout
- /authenticated.jsp = authc
- /** = user
- </value>
- </property>
- </bean>
SpringShiroFilter对 象,即Spring配置文件中的shiroFilter对象,该过滤器拥有三个重要对象:
SecurityManager、
PathMatchingFilterChainResolver、
FilterChainManager
当匹配到过滤链中的aauthc对应的url时,会执行匹配对应<entry key="authc" value-ref="formAuthenticationFilter"/>,既然是filter,那么最
重要的就是doFilter方法了,经过执行父类的一系列方法后最终执行到FormAuthenticationFilter类中的onAccessDenied方法的
- protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
- // 第一次访问自然不是登录请求
- if (isLoginRequest(request, response)) {
- // 判断是否是POST请求
- if (isLoginSubmission(request, response)) {
- if (log.isTraceEnabled()) {
- log.trace("Login submission detected. Attempting to execute login.");
- }
- return executeLogin(request, response);
接着执行父类AuthenticatingFilter中的executeLogin()方法,创建token的方法createToken()可以重写放回自定义实现UsernamePasswordToken的
类MyUsernamePasswordToken(可以实现实际的业务逻辑)
- protected boolean executeLogin(ServletRequest request, ServletResponse response) throws Exception {
- // 根据表单填写的用户名密码创建AuthenticationToken
- AuthenticationToken token = createToken(request, response);
- if (token == null) {
- String msg = "createToken method implementation returned null. A valid non-null AuthenticationToken " +
- "must be created in order to execute a login attempt.";
- throw new IllegalStateException(msg);
- }
- try {
- // 获取Subject对象
- Subject subject = getSubject(request, response);
- // 执行Subject.login方法进行登录
- subject.login(token);
- // 如果登录成功,重定向至上次访问的URL
- return onLoginSuccess(token, subject, request, response);
接着执行subject的实现类DelegatingSubject中的login()方法
接着执行securityManager实现类DefaultSecurityManager的login()方法
接着执行AuthenticatingSecurityManager中的authenticate( )方法,该方法this.authenticator返回的是ModularRealmAuthenticator
执行ModularRealmAuthenticator中的authenticaticate( )方法,因为其继承AbstractAuthenticator,所以执行AbstractAuthenticator中的authenticaticate( )
接着执行ModularRealmAuthenticator中的doAuthenticate( )方法
其中realm.getAuthenticationInfo( ),realm为Realm接口,实际上调用的是其实现类AuthenticatingRealm中的getAuthenticationInfo( )方法
上述代码AuthenticationInfo info = getCachedAuthenticationInfo(token);从缓存中获取认证信息,如果未获取到,则调用doGetAuthenticationInfo(token)
方法获取认证信息,获取到认证信息info后执行assertCredentialsMatch( )方法
getCredentialsMatcher( )返回我们自定义实现SimpleCredentialsMatcher的类MyCredentialsMatcher,接着cm.doCredentialMatch( )调用实现类方法
校验成功后则执行下面的跳转方法onLoginSuccess( )
接着执行实现FormAuthenticationFilter的方法
认证成功执行FormAuthenticationFilter中的onLoginSuccess()方法,调用issueSuccessRedirect( ),
接着执行AuthenticationFilter中的issueSuccessRedirect( )
认证失败则执行FormAuthenticationFilter中的onLoginFailure方法,接着执行FormAuthenticationFilter中的setFailureAttribute( )方法
getFailureKeyAttribute( )方法返回的事一个final字符窜:DEFAULT_ERROR_KEY_ATTRIBUTE_NAME
接着在LoginController中获取到key对应的值进行异常抛出
参考文献:http://www.cnblogs.com/ccfdod/p/6436353.html
http://blog.csdn.net/xtayfjpk/article/details/53729135
http://jinnianshilongnian.iteye.com/blog/2029717