Apache Shiro 身份认证例子



在本例子中使用Apache ShiroWeb应用中实现身份认证,将Shirospring进行集成,使用内嵌的derby数据库存储用户信息。

持久层为hibernate,数据库连接池为alibaba druid。

2. 准备

创建一个内嵌的derby数据库,本例使用的是db-derby-10.10.1.1

2.1 建表

Create table users(

Id int primary key,

Name varchar(20),

Passwd varchar(20)

);

2.2 初始化数据

Insert into users values(1,’admin’,’admin’);

Insert into users values(2,’peter’,’peter’);

3. 配置

3.1 Web.xml

[html]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. <!-- Apache Shiro -->  
  2. <filter>  
  3. <filter-name>shiroFilter</filter-name>  
  4. <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>  
  5. <init-param>  
  6. <param-name>targetFilterLifecycle</param-name>  
  7. <param-value>true</param-value>  
  8. </init-param>  
  9. </filter>  
  10. <filter-mapping>  
  11. <filter-name>shiroFilter</filter-name>  
  12. <url-pattern>/*</url-pattern>  
  13. </filter-mapping>  

3.2 ApplicationContext.xml

[html]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. <!-- 安全认证过滤器 -->  
  2.     <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">  
  3.         <property name="securityManager" ref="securityManager" />  
  4.         <property name="loginUrl" value="/index.do" />  
  5.           
  6.         <property name="filterChainDefinitions">  
  7.             <value>  
  8.                 /login.do = anon  
  9.                 /** = authc  
  10.   
  11.             </value>  
  12.         </property>  
  13.     </bean>  
  14.   
  15.     <!-- 定义 Shiro 主要业务对象 -->  
  16.     <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">  
  17.         <property name="realm" ref="systemAuthorizingRealm" />  
  18.     </bean>  
  19.   
  20.     <!-- 保证实现了Shiro内部lifecycle函数的bean执行 -->  
  21.     <bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor" />  


4. 认证

登录JSP
[html]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. <%@ page language="java" contentType="text/html; charset=UTF-8"  
  2.     pageEncoding="UTF-8"%>  
  3. <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">  
  4. <html>  
  5. <head>  
  6. <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">  
  7. <title>Login</title>  
  8. </head>  
  9. <body>  
  10.     <form id="form1" name="form1" method="post" action="login.do">  
  11.         <p align="center">用户登录</p>  
  12.         <table width="296" border="1" align="center" bgcolor="#00FF99">  
  13.             <tr>  
  14.                 <td width="98" height="34">用户名:</td>  
  15.                 <td width="182"><label><input name="loginName"  
  16.                         type="text" id="loginName" /> </label></td>  
  17.             </tr>  
  18.   
  19.             <tr>  
  20.                 <td height="36">密码:</td>  
  21.                 <td><label> <input name="password" type="password"  
  22.                         id="password" />  
  23.                 </label></td>  
  24.             </tr>  
  25.             <tr>  
  26.                 <td height="35" colspan="2"><label>        
  27.                         <input type="submit" name="Submit" value="提交" />  
  28.                 </label> <label>       <input  
  29.                         type="reset" name="Submit2" value="重置" />  
  30.                 </label></td>  
  31.             </tr>  
  32.         </table>  
  33.     </form>  
  34. </body>  
  35. </html>  

Web控制器
[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. @Controller  
  2. public class LoginController {  
  3.     private static final Logger LOGGER = LoggerFactory.getLogger(LoginController.class);  
  4.   
  5.     @RequestMapping(value = "/login.do", method = RequestMethod.POST)  
  6.     public String isLogin(HttpServletRequest request, PasswordAuthcInfo passwordAuthcInfo) {  
  7.         String loginName = passwordAuthcInfo.getLoginName();  
  8.         String loginPassword = passwordAuthcInfo.getPassword();  
  9.         LOGGER.info("loginName:" + loginName + ";loginPassword:" + loginPassword);  
  10.   
  11.         HttpSession session = request.getSession(true);  
  12.         String errorMessage = "";  
  13.   
  14.         Subject user = SecurityUtils.getSubject();  
  15.   
  16.         UsernamePasswordToken token = new UsernamePasswordToken(loginName, loginPassword);  
  17.         token.setRememberMe(true);  
  18.   
  19.         try {  
  20.             user.login(token);  
  21.             String userID = (String) user.getPrincipal();  
  22.             LOGGER.info("User [" + userID + "] logged in successfully.");  
  23.   
  24.             session.setAttribute("USERNAME", userID);  
  25.             return "success";  
  26.         } catch (UnknownAccountException uae) {  
  27.             errorMessage = "用户认证失败:" + "username wasn't in the system.";  
  28.             LOGGER.info(errorMessage);  
  29.         } catch (IncorrectCredentialsException ice) {  
  30.             errorMessage = "用户认证失败:" + "password didn't match.";  
  31.             LOGGER.info(errorMessage);  
  32.         } catch (LockedAccountException lae) {  
  33.             errorMessage = "用户认证失败:" + "account for that username is locked - can't login.";  
  34.             LOGGER.info(errorMessage);  
  35.         } catch (AuthenticationException e) {  
  36.             errorMessage = "登录失败错误信息:" + e;  
  37.             LOGGER.error(errorMessage);  
  38.             e.printStackTrace();  
  39.             token.clear();  
  40.         }  
  41.         session.setAttribute("ErrorMessage", errorMessage);  
  42.         return "error";  
  43.     }  
  44. }  

认证服务类
[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. @Service  
  2. public class SystemAuthorizingRealm extends AuthorizingRealm {  
  3.   
  4.     @Resource(name = "userService")  
  5.     private UserService userService;  
  6.   
  7.     // 授权  
  8.     protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection arg0) {  
  9.         // TODO Auto-generated method stub  
  10.         return null;  
  11.     }  
  12.   
  13.     // 认证  
  14.     protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authcToken) throws AuthenticationException {  
  15.         UsernamePasswordToken token = (UsernamePasswordToken) authcToken;  
  16.   
  17.         Users user = userService.getUser(token.getUsername());  
  18.         if (user != null) {  
  19.             return new SimpleAuthenticationInfo(user.getName(), user.getPassword(), "");  
  20.         } else {  
  21.             return null;  
  22.         }  
  23.     }  
  24. }  

用户服务类
[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. @Service("userService")  
  2. public class UserServiceImpl implements UserService {  
  3.   
  4.   
  5. <span style="white-space:pre">  </span>@Autowired  
  6. <span style="white-space:pre">  </span>private UserDao userDao;  
  7.   
  8.   
  9. <span style="white-space:pre">  </span>public Users getUser(String userName) {  
  10. <span style="white-space:pre">      </span>Users users = null;  
  11. <span style="white-space:pre">      </span>try {  
  12. <span style="white-space:pre">          </span>users = userDao.searchUser(userName);  
  13. <span style="white-space:pre">      </span>} catch (DataAccessException e) {  
  14. <span style="white-space:pre">          </span>e.printStackTrace();  
  15. <span style="white-space:pre">      </span>}  
  16. <span style="white-space:pre">      </span>return users;  
  17. <span style="white-space:pre">  </span>}  
  18. }  

数据库操作类
[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. @Repository("UserDao")  
  2. public class UserDaoImpl extends BaseDaoImpl implements UserDao {  
  3. <span style="white-space:pre">  </span>  
  4. <span style="white-space:pre">  </span>public Users searchUser(String userName) throws DataAccessException{  
  5. <span style="white-space:pre">      </span>Users users = null;  
  6. <span style="white-space:pre">      </span>try {  
  7. <span style="white-space:pre">          </span>Session session = sessionFactory.openSession();  
  8. <span style="white-space:pre">          </span>Query query = session.createQuery("from Users a where a.name=:name").setString(  
  9. <span style="white-space:pre">                  </span>"name", userName);  
  10. <span style="white-space:pre">          </span>users = (Users) query.uniqueResult();  
  11. <span style="white-space:pre">          </span>session.close();  
  12. <span style="white-space:pre">      </span>} catch (Throwable e) {  
  13. <span style="white-space:pre">          </span>throw new DataAccessException(e);  
  14. <span style="white-space:pre">      </span>}  
  15. <span style="white-space:pre">      </span>return users;  
  16. <span style="white-space:pre">  </span>  
  17. <span style="white-space:pre">  </span>}  
  18. }  


5. 内置表单过滤器

上面的程序是使用Spring的Web控制器来获取页面提交的数据,也可以使用Shiro内置的表单过滤器来实现页面数据提交。
修改applicationContext.xml增加过滤器
[html]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">  
  2.         <property name="securityManager" ref="securityManager" />  
  3.         <property name="loginUrl" value="/login.do" />  
  4.         <property name="successUrl" value="/main.do" />  
  5.         <property name="unauthorizedUrl" value="/error.do" />    
  6.         <property name="filters">  
  7.             <util:map>  
  8.                 <entry key="authc">  
  9.                     <bean class="com.peter.smallshow.security.CustomFormAuthenticationFilter">  
  10.                         <property name="usernameParam" value="loginName" />  
  11.                         <property name="passwordParam" value="password" />  
  12.                     </bean>  
  13.                 </entry>  
  14.             </util:map>  
  15.         </property>  
  16.         <property name="filterChainDefinitions">  
  17.             <value>  
  18.                 /index.do = anon  
  19.                 /login.do = authc  
  20.                 /** = authc  
  21.   
  22.             </value>  
  23.         </property>  
  24.     </bean>  

表单中的参数固定写法是username、password、rememberMe。
可以通过<property name="usernameParam" value="loginName" />来设置
自定义的表单过滤类
[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. @Service  
  2. public class CustomFormAuthenticationFilter extends FormAuthenticationFilter {  
  3.     protected AuthenticationToken createToken(ServletRequest request, ServletResponse response) {  
  4.         String username = getUsername(request);  
  5.         String password = getPassword(request);  
  6.         if (password == null) {  
  7.             password = "";  
  8.         }  
  9.         boolean rememberMe = false;  
  10.         String host = getHost(request);  
  11.         return new UsernamePasswordToken(username, password.toCharArray(), rememberMe, host);  
  12.   
  13.     }  
  14.   
  15. }  

6.工程代码


Web应用:smallShow.war  直接放到Tomcat下即可。  http://download.csdn.net/detail/peterwanghao/6858127

在本例子中使用Apache ShiroWeb应用中实现身份认证,将Shirospring进行集成,使用内嵌的derby数据库存储用户信息。

持久层为hibernate,数据库连接池为alibaba druid。

2. 准备

创建一个内嵌的derby数据库,本例使用的是db-derby-10.10.1.1

2.1 建表

Create table users(

Id int primary key,

Name varchar(20),

Passwd varchar(20)

);

2.2 初始化数据

Insert into users values(1,’admin’,’admin’);

Insert into users values(2,’peter’,’peter’);

3. 配置

3.1 Web.xml

[html]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. <!-- Apache Shiro -->  
  2. <filter>  
  3. <filter-name>shiroFilter</filter-name>  
  4. <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>  
  5. <init-param>  
  6. <param-name>targetFilterLifecycle</param-name>  
  7. <param-value>true</param-value>  
  8. </init-param>  
  9. </filter>  
  10. <filter-mapping>  
  11. <filter-name>shiroFilter</filter-name>  
  12. <url-pattern>/*</url-pattern>  
  13. </filter-mapping>  

3.2 ApplicationContext.xml

[html]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. <!-- 安全认证过滤器 -->  
  2.     <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">  
  3.         <property name="securityManager" ref="securityManager" />  
  4.         <property name="loginUrl" value="/index.do" />  
  5.           
  6.         <property name="filterChainDefinitions">  
  7.             <value>  
  8.                 /login.do = anon  
  9.                 /** = authc  
  10.   
  11.             </value>  
  12.         </property>  
  13.     </bean>  
  14.   
  15.     <!-- 定义 Shiro 主要业务对象 -->  
  16.     <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">  
  17.         <property name="realm" ref="systemAuthorizingRealm" />  
  18.     </bean>  
  19.   
  20.     <!-- 保证实现了Shiro内部lifecycle函数的bean执行 -->  
  21.     <bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor" />  


4. 认证

登录JSP
[html]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. <%@ page language="java" contentType="text/html; charset=UTF-8"  
  2.     pageEncoding="UTF-8"%>  
  3. <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">  
  4. <html>  
  5. <head>  
  6. <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">  
  7. <title>Login</title>  
  8. </head>  
  9. <body>  
  10.     <form id="form1" name="form1" method="post" action="login.do">  
  11.         <p align="center">用户登录</p>  
  12.         <table width="296" border="1" align="center" bgcolor="#00FF99">  
  13.             <tr>  
  14.                 <td width="98" height="34">用户名:</td>  
  15.                 <td width="182"><label><input name="loginName"  
  16.                         type="text" id="loginName" /> </label></td>  
  17.             </tr>  
  18.   
  19.             <tr>  
  20.                 <td height="36">密码:</td>  
  21.                 <td><label> <input name="password" type="password"  
  22.                         id="password" />  
  23.                 </label></td>  
  24.             </tr>  
  25.             <tr>  
  26.                 <td height="35" colspan="2"><label>        
  27.                         <input type="submit" name="Submit" value="提交" />  
  28.                 </label> <label>       <input  
  29.                         type="reset" name="Submit2" value="重置" />  
  30.                 </label></td>  
  31.             </tr>  
  32.         </table>  
  33.     </form>  
  34. </body>  
  35. </html>  

Web控制器
[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. @Controller  
  2. public class LoginController {  
  3.     private static final Logger LOGGER = LoggerFactory.getLogger(LoginController.class);  
  4.   
  5.     @RequestMapping(value = "/login.do", method = RequestMethod.POST)  
  6.     public String isLogin(HttpServletRequest request, PasswordAuthcInfo passwordAuthcInfo) {  
  7.         String loginName = passwordAuthcInfo.getLoginName();  
  8.         String loginPassword = passwordAuthcInfo.getPassword();  
  9.         LOGGER.info("loginName:" + loginName + ";loginPassword:" + loginPassword);  
  10.   
  11.         HttpSession session = request.getSession(true);  
  12.         String errorMessage = "";  
  13.   
  14.         Subject user = SecurityUtils.getSubject();  
  15.   
  16.         UsernamePasswordToken token = new UsernamePasswordToken(loginName, loginPassword);  
  17.         token.setRememberMe(true);  
  18.   
  19.         try {  
  20.             user.login(token);  
  21.             String userID = (String) user.getPrincipal();  
  22.             LOGGER.info("User [" + userID + "] logged in successfully.");  
  23.   
  24.             session.setAttribute("USERNAME", userID);  
  25.             return "success";  
  26.         } catch (UnknownAccountException uae) {  
  27.             errorMessage = "用户认证失败:" + "username wasn't in the system.";  
  28.             LOGGER.info(errorMessage);  
  29.         } catch (IncorrectCredentialsException ice) {  
  30.             errorMessage = "用户认证失败:" + "password didn't match.";  
  31.             LOGGER.info(errorMessage);  
  32.         } catch (LockedAccountException lae) {  
  33.             errorMessage = "用户认证失败:" + "account for that username is locked - can't login.";  
  34.             LOGGER.info(errorMessage);  
  35.         } catch (AuthenticationException e) {  
  36.             errorMessage = "登录失败错误信息:" + e;  
  37.             LOGGER.error(errorMessage);  
  38.             e.printStackTrace();  
  39.             token.clear();  
  40.         }  
  41.         session.setAttribute("ErrorMessage", errorMessage);  
  42.         return "error";  
  43.     }  
  44. }  

认证服务类
[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. @Service  
  2. public class SystemAuthorizingRealm extends AuthorizingRealm {  
  3.   
  4.     @Resource(name = "userService")  
  5.     private UserService userService;  
  6.   
  7.     // 授权  
  8.     protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection arg0) {  
  9.         // TODO Auto-generated method stub  
  10.         return null;  
  11.     }  
  12.   
  13.     // 认证  
  14.     protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authcToken) throws AuthenticationException {  
  15.         UsernamePasswordToken token = (UsernamePasswordToken) authcToken;  
  16.   
  17.         Users user = userService.getUser(token.getUsername());  
  18.         if (user != null) {  
  19.             return new SimpleAuthenticationInfo(user.getName(), user.getPassword(), "");  
  20.         } else {  
  21.             return null;  
  22.         }  
  23.     }  
  24. }  

用户服务类
[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. @Service("userService")  
  2. public class UserServiceImpl implements UserService {  
  3.   
  4.   
  5. <span style="white-space:pre">  </span>@Autowired  
  6. <span style="white-space:pre">  </span>private UserDao userDao;  
  7.   
  8.   
  9. <span style="white-space:pre">  </span>public Users getUser(String userName) {  
  10. <span style="white-space:pre">      </span>Users users = null;  
  11. <span style="white-space:pre">      </span>try {  
  12. <span style="white-space:pre">          </span>users = userDao.searchUser(userName);  
  13. <span style="white-space:pre">      </span>} catch (DataAccessException e) {  
  14. <span style="white-space:pre">          </span>e.printStackTrace();  
  15. <span style="white-space:pre">      </span>}  
  16. <span style="white-space:pre">      </span>return users;  
  17. <span style="white-space:pre">  </span>}  
  18. }  

数据库操作类
[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. @Repository("UserDao")  
  2. public class UserDaoImpl extends BaseDaoImpl implements UserDao {  
  3. <span style="white-space:pre">  </span>  
  4. <span style="white-space:pre">  </span>public Users searchUser(String userName) throws DataAccessException{  
  5. <span style="white-space:pre">      </span>Users users = null;  
  6. <span style="white-space:pre">      </span>try {  
  7. <span style="white-space:pre">          </span>Session session = sessionFactory.openSession();  
  8. <span style="white-space:pre">          </span>Query query = session.createQuery("from Users a where a.name=:name").setString(  
  9. <span style="white-space:pre">                  </span>"name", userName);  
  10. <span style="white-space:pre">          </span>users = (Users) query.uniqueResult();  
  11. <span style="white-space:pre">          </span>session.close();  
  12. <span style="white-space:pre">      </span>} catch (Throwable e) {  
  13. <span style="white-space:pre">          </span>throw new DataAccessException(e);  
  14. <span style="white-space:pre">      </span>}  
  15. <span style="white-space:pre">      </span>return users;  
  16. <span style="white-space:pre">  </span>  
  17. <span style="white-space:pre">  </span>}  
  18. }  


5. 内置表单过滤器

上面的程序是使用Spring的Web控制器来获取页面提交的数据,也可以使用Shiro内置的表单过滤器来实现页面数据提交。
修改applicationContext.xml增加过滤器
[html]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">  
  2.         <property name="securityManager" ref="securityManager" />  
  3.         <property name="loginUrl" value="/login.do" />  
  4.         <property name="successUrl" value="/main.do" />  
  5.         <property name="unauthorizedUrl" value="/error.do" />    
  6.         <property name="filters">  
  7.             <util:map>  
  8.                 <entry key="authc">  
  9.                     <bean class="com.peter.smallshow.security.CustomFormAuthenticationFilter">  
  10.                         <property name="usernameParam" value="loginName" />  
  11.                         <property name="passwordParam" value="password" />  
  12.                     </bean>  
  13.                 </entry>  
  14.             </util:map>  
  15.         </property>  
  16.         <property name="filterChainDefinitions">  
  17.             <value>  
  18.                 /index.do = anon  
  19.                 /login.do = authc  
  20.                 /** = authc  
  21.   
  22.             </value>  
  23.         </property>  
  24.     </bean>  

表单中的参数固定写法是username、password、rememberMe。
可以通过<property name="usernameParam" value="loginName" />来设置
自定义的表单过滤类
[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. @Service  
  2. public class CustomFormAuthenticationFilter extends FormAuthenticationFilter {  
  3.     protected AuthenticationToken createToken(ServletRequest request, ServletResponse response) {  
  4.         String username = getUsername(request);  
  5.         String password = getPassword(request);  
  6.         if (password == null) {  
  7.             password = "";  
  8.         }  
  9.         boolean rememberMe = false;  
  10.         String host = getHost(request);  
  11.         return new UsernamePasswordToken(username, password.toCharArray(), rememberMe, host);  
  12.   
  13.     }  
  14.   
  15. }  

6.工程代码


Web应用:smallShow.war  直接放到Tomcat下即可。  http://download.csdn.net/detail/peterwanghao/6858127
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值