自己的项目中很多都用到了Shiro的配置来管理验证登录和权限认证,所以自己简单的小结一下,这里暂时只解释登录验证这一块。
(1)首先在项目的WEB-INF目录下的web.xml配置中:
加上
01 <!-- Shiro Security filter -->
02 <filter>
03 <filter-name>shiroFilter</filter-name>
04 <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
05 </filter>
06 <filter-mapping>
07 <filter-name>shiroFilter</filter-name>
08 <url-pattern>*.htm</url-pattern>
09 <dispatcher>REQUEST</dispatcher>
10 <dispatcher>FORWARD</dispatcher>
11 </filter-mapping>
12 <filter-mapping>
13 <filter-name>shiroFilter</filter-name>
14 <url-pattern>*.json</url-pattern>
15 <dispatcher>REQUEST</dispatcher>
16 <dispatcher>FORWARD</dispatcher>
17 </filter-mapping>
18 <filter-mapping>
19 <filter-name>shiroFilter</filter-name>
20 <url-pattern>*.jsp</url-pattern>
21 <dispatcher>REQUEST</dispatcher>
22 <dispatcher>FORWARD</dispatcher>
23 </filter-mapping>
24 <!-- Shiro Security filter -->
上面的配置是对请求地址后缀的过滤和转发
这里我的欢迎页的配置直接配置login.jsp了。还是在web.xml中最后加上
<welcome-file-list>
<welcome-file>login.jsp</welcome-file>
</welcome-file-list>
(2)在项目的上下文配置applicationContext.xml中加上:
<import resource="security/applicationContext-shiro.xml" />
这样的话,就能引入applicationContext-shiro.xml的配置,在这个配置中
全文配置如下:
01 <?xml version="1.0" encoding="UTF-8"?>
02 <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
03 xmlns:util="http://www.springframework.org/schema/util"
04 xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-2.0.xsd"
05 default-lazy-init="true">
06
07 <description>Shiro安全配置</description>
08
09 <!-- Shiro's main business-tier object for web-enabled applications -->
10 <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
11 <property name="realm" ref="shiroDbRealm" />
12 <property name="cacheManager" ref="shiroEhcacheManager" />
13 </bean>
14
15 <!-- 項目自定义的Realm -->
16 <bean id="shiroDbRealm" class="com.baishi.website.User.MyDbRealm">
17 <property name="userService" ref="userService"/>
18 <!-- 可配置cache token<->认证信息的cache,用于REST等需要频繁认证的场景 -->
19 <!--<property name="authorizationCachingEnabled" value="true"/>-->
20 </bean>
21
22 <bean id="myAuthc" class="com.baishi.website.base.filter.MyFormAuthenticationFilter"/>
23
24 <!-- Shiro Filter -->
25 <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
26 <property name="securityManager" ref="securityManager" />
27 <property name="loginUrl" value="/login.htm" />
28 <property name="successUrl" value="/admin.htm" />
29 <property name="unauthorizedUrl" value="/unauthorized.htm"/>
30 <property name="filters">
31 <util:map>
32 <entry key="myAuthc" value-ref="myAuthc"/>
33 </util:map>
34 </property>
35 <property name="filterChainDefinitions">
36 <value>
37 /logout.htm = logout
38 /** = myAuthc
39 </value>
40 </property>
41 </bean>
42
43 <!-- 用户授权信息Cache, 采用EhCache -->
44 <bean id="shiroEhcacheManager" class="org.apache.shiro.cache.ehcache.EhCacheManager">
45 <property name="cacheManagerConfigFile" value="classpath:security/ehcache-shiro.xml"/>
46 </bean>
47
48 <!-- 保证实现了Shiro内部lifecycle函数的bean执行 -->
49 <bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/>
50
51 <!-- AOP式方法级权限检查 -->
52 <bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator" depends-on="lifecycleBeanPostProcessor">
53 <property name="proxyTargetClass" value="true" />
54 </bean>
55 <bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">
56 <property name="securityManager" ref="securityManager"/>
57 </bean>
58 </beans>
这里面我们关注的是:項目自定义的Realm,在我的目录下com.baishi.website.User.MyDbRealm找到 MyDbRealm这个类
MyDbRealm类的代码如下:
01 package com.baishi.website.User;
02
03 import com.baishi.website.entity.Users;
04 import org.apache.shiro.authc.*;
05 import org.apache.shiro.authz.AuthorizationInfo;
06 import org.apache.shiro.authz.SimpleAuthorizationInfo;
07 import org.apache.shiro.realm.AuthorizingRealm;
08 import org.apache.shiro.subject.PrincipalCollection;
09
10 public class MyDbRealm extends AuthorizingRealm {
11
12 private UserService userService;
13
14 /**
15 * 认证回调函数,登录时调用.
16 */
17 @Override
18 protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
19 UsernamePasswordToken upToken = (UsernamePasswordToken) token;
20 Users user = userService.findUserByLoginName(upToken.getUsername());
21 if (user == null) {
22 throw new UnknownAccountException("No account found for user [" + user.getUsername() + "]");
23 }
24
25 return new SimpleAuthenticationInfo(user, user.getPassword(), getName());
26 }
27
28 /**
29 * 授权查询回调函数, 进行鉴权但缓存中无用户的授权信息时调用.
30 */
31 @Override
32 protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
33 Users user = (Users) principals.fromRealm(getName()).iterator().next();
34 //user = userService.findAuthDetails(user);
35 if (user != null) {
36 SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
37 // for (Role role : user.getRoles()) {
38 // //基于Role的权限信息
39 // info.addRole(role.getName());
40 // }
41 // info.addStringPermissions(user.getPermissions());
42 return info;
43 } else {
44 return null;
45 }
46 }
47
48 public void setUserService(UserService userService) {
49 this.userService = userService;
50 }
51 }
其中你只要关注:认证回调函数,登录时调用这个方法,到时候断点到这里看一下验证。
继续解释applicationContext-shiro.xml的配置:其中MyFormAuthenticationFilter这个类是超时的类配置:
代码如下:
package com.baishi.website.base.filter;
import org.apache.ibatis.logging.LogFactory;
import org.apache.shiro.web.filter.authc.FormAuthenticationFilter;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class MyFormAuthenticationFilter extends FormAuthenticationFilter {
static {
LogFactory.useStdOutLogging();
}
@Override
protected void saveRequestAndRedirectToLogin(ServletRequest request, ServletResponse response) throws IOException {
HttpServletRequest request1 = (HttpServletRequest) request;
HttpServletResponse response1 = (HttpServletResponse) response;
String uri = request1.getRequestURI();
if (uri.endsWith(".json")) {
response1.setHeader("sessionstatus", "timeout");
} else {
saveRequest(request);
redirectToLogin(request, response);
}
}
}
继续解释配置中<property name="loginUrl" value="/login.htm" />
<property name="successUrl" value="/admin.htm" />
两个属性对应的是登录和成功登录后的两个页面,这里我是在webapp根目录的两个页面:
其中login,jsp的页面代码:
01 <%@ page language="java" contentType="text/html" pageEncoding="UTF-8"%>
02 <%@taglib prefix="shiro" uri="http://shiro.apache.org/tags" %>
03
04 <%
05 String path = request.getContextPath();
06 String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + path + "/";
07 %>
08 <html>
09 <head>
10 <base href="<%=basePath%>">
11 <title>博客后台登陆</title>
12 <shiro:authenticated>
13 <script type="text/javascript">
14 window.location.href = 'index.htm';
15 </script>
16 </shiro:authenticated>
17 </head>
18
19 <body>
20 <p>用户登录</p>
21
22 <form id="form1" name="form1" method="post" action="login.htm">
23 <input type="hidden" name="method" value="login" />
24 <table width="335" height="84" border="0" cellpadding="1" cellspacing="1">
25 <tr>
26 <td>用户名:</td>
27 <td><label>
28 <input type="text" name="username" id="username" />
29 </label></td>
30 </tr>
31 <tr>
32 <td>密码:</td>
33 <td><label>
34 <input type="password" name="password" id="password" />
35 </label></td>
36 </tr>
37 <tr>
38 <td><label>
39 <input type="submit" name="button" id="button" value="登录" />
40 </label></td>
41 <td><label></label></td>
42 </tr>
43 </table>
44 </form>
45 <p> </p>
46 </body>
47
48 </html>
其中引入shiro的标签,并且
1 <shiro:authenticated>
2 <script type="text/javascript">
3 window.location.href = 'index.htm';
4 </script>
5 </shiro:authenticated>
重定向到index.htm这个页面。
另外在applicationContext-shiro.xml的配置中引入
<!-- 用户授权信息Cache, 采用EhCache -->
<bean id="shiroEhcacheManager" class="org.apache.shiro.cache.ehcache.EhCacheManager">
<property name="cacheManagerConfigFile" value="classpath:security/ehcache-shiro.xml"/>
</bean>
ehcache-shiro.xml的配置如下:
view sourceprint?01 <ehcache updateCheck="false" name="shiroCache">
02
03 <defaultCache
04 maxElementsInMemory="10000"
05 eternal="false"
06 timeToIdleSeconds="120"
07 timeToLiveSeconds="120"
08 overflowToDisk="false"
09 diskPersistent="false"
10 diskExpiryThreadIntervalSeconds="120"
11 />
12 </ehcache>
到此 applicationContext-shiro.xml的配置就完成了。
现在实际操作的时候,在用户的Controller类中,我们写上简单代码:
01 package com.baishi.website.User;
02
03 import com.alibaba.fastjson.JSON;
04 import com.baishi.website.base.support.BaseControllerSupport;
05 import com.baishi.website.entity.Users;
06 import org.springframework.stereotype.Controller;
07 import org.springframework.ui.Model;
08 import org.springframework.web.bind.annotation.RequestMapping;
09 import org.springframework.web.bind.annotation.RequestMethod;
10 import javax.annotation.Resource;
11 import javax.servlet.http.HttpServletRequest;
12 import java.util.List;
13 import java.util.Map;
14
15 @Controller
16 @RequestMapping
17 public class UserController extends BaseControllerSupport {
18 /**
19 * 用户登录后台
20 */
21 @RequestMapping(value = "/login", method = RequestMethod.POST)
22 public String home(){
23 return "login";
24 }
25
26 @RequestMapping(value = "/login", method = RequestMethod.GET)
27 public String login() {
28 return "login";
29 }
30
31 @RequestMapping(value = {"admin","index"})
32 public String admin() {
33 return "admin";
34 }
view sourceprint?1 }
最后还要说的是在MyDbRealm类中findUserByLoginName()这个方法,自己简单的在service层写一个根据用户名查询数据库的方法就行了,在xml 中的查询语句:
<select id="findByLoginName" parameterType="String" resultType="Users">
SELECT
*
FROM users
WHERE
username=#{username}
LIMIT 1
</select>
到此就简单的介绍了,用shiro验证登录的配置。解释一下整个过程的流程吧,启动tomcat,首先进入web.xml中过滤→到Controller类中转到视图页面login.jsp→进入了登录的页面,填入信息提交→到MyDbRealm类中验证回调的方法→验证成功后重定向到主页admin.htm