常用框架(三):spring+springMvc+mybatis+maven+shiro+freemarker

在之前的博文,常用框架(一)中讲述了spring+springMvc+mybatis+maven框架的搭建,而在常用框架(二)中又集成了Redis

这篇文章主要讲述如何集成shiro+freemarker及其简单应用,还是在原有项目上做扩展,

需要回顾的请点链接跳转:http://blog.csdn.net/mynoteblog/article/details/54922775


项目说明:

(1) 使用freemarker模板,在html页面中可以获取attribute参数,替代jsp。

(2) 使用shiro做登录验证,以及权限分配

(3) pom.xml 追加依赖,这里加入了日志框架,源码会分享,这里就不做介绍了:

[html]  view plain  copy
  1. <!-- freemarker -->  
  2. <dependency>  
  3.     <groupId>org.freemarker</groupId>  
  4.     <artifactId>freemarker</artifactId>  
  5.     <version>2.3.23</version>  
  6. </dependency>       
  7.   
  8. <!-- Spring 整合Shiro需要的依赖 -->  
  9. <dependency>  
  10.     <groupId>org.apache.shiro</groupId>  
  11.     <artifactId>shiro-core</artifactId>  
  12.     <version>${shiro.version}</version>  
  13. </dependency>  
  14. <dependency>  
  15.     <groupId>org.apache.shiro</groupId>  
  16.     <artifactId>shiro-web</artifactId>  
  17.     <version>${shiro.version}</version>  
  18. </dependency>  
  19. <dependency>  
  20.     <groupId>org.apache.shiro</groupId>  
  21.     <artifactId>shiro-ehcache</artifactId>  
  22.     <version>${shiro.version}</version>  
  23. </dependency>  
  24. <dependency>  
  25.     <groupId>org.apache.shiro</groupId>  
  26.     <artifactId>shiro-spring</artifactId>  
  27.     <version>${shiro.version}</version>  
  28. </dependency>  
  29. <dependency>  
  30.     <groupId>org.apache.shiro</groupId>  
  31.     <artifactId>shiro-freemarker-tags</artifactId>  
  32.     <version>0.1-SNAPSHOT</version>  
  33.     <exclusions>  
  34.         <exclusion>  
  35.             <artifactId>javax.servlet-api</artifactId>  
  36.             <groupId>javax.servlet</groupId>  
  37.         </exclusion>  
  38.     </exclusions>  
  39. </dependency>  
  40.   
  41. <!-- slf4j日志框架 -->  
  42. <dependency>  
  43.     <groupId>org.slf4j</groupId>  
  44.     <artifactId>slf4j-api</artifactId>  
  45.     <version>${slf4j.version}</version>  
  46. </dependency>  
  47. <dependency>  
  48.     <groupId>ch.qos.logback</groupId>  
  49.     <artifactId>logback-classic</artifactId>  
  50.     <version>1.1.3</version>  
  51. </dependency>  
  52. <dependency>  
  53.     <groupId>org.slf4j</groupId>  
  54.     <artifactId>jcl-over-slf4j</artifactId>  
  55.     <version>${slf4j.version}</version>  
  56. </dependency>  
  57. <dependency>  
  58.     <groupId>org.slf4j</groupId>  
  59.     <artifactId>log4j-over-slf4j</artifactId>  
  60.     <version>${slf4j.version}</version>  
  61. </dependency>  
  62. <dependency>  
  63.     <groupId>org.logback-extensions</groupId>  
  64.     <artifactId>logback-ext-spring</artifactId>  
  65.     <version>0.1.2</version>  
  66. </dependency>  

一,整合freemarker,新建Spring-freemarker.xml,配置如下:

[html]  view plain  copy
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <beans xmlns="http://www.springframework.org/schema/beans"  
  3.        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
  4.        xmlns:p="http://www.springframework.org/schema/p"  
  5.        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd">  
  6.   
  7.     <!-- 配置freeMarker的模板路径 -->  
  8.     <bean id="freemarkerConfig"  
  9.         class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer">  
  10.         <!-- 模板页面放置位置 -->  
  11.         <property name="templateLoaderPaths" value="/WEB-INF/template/" />  
  12.         <property name="freemarkerSettings">  
  13.             <props>  
  14.                 <prop key="tag_syntax">auto_detect</prop>  
  15.                 <prop key="template_update_delay">0</prop>  
  16.                 <prop key="default_encoding">UTF-8</prop>  
  17.                 <prop key="output_encoding">UTF-8</prop>  
  18.                 <prop key="locale">zh_CN</prop>  
  19.                 <prop key="number_format">0.##########</prop>  
  20.                 <prop key="boolean_format">true,false</prop>  
  21.                 <prop key="datetime_format">yyyy-MM-dd HH:mm:ss</prop>  
  22.                 <prop key="date_format">yyyy-MM-dd</prop>  
  23.                 <prop key="time_format">HH:mm:ss</prop>  
  24.                 <prop key="classic_compatible">true</prop>  
  25.                 <prop key="whitespace_stripping">true</prop>  
  26.                 <prop key="template_exception_handler">ignore</prop>  
  27.             </props>  
  28.         </property>  
  29.   
  30. </beans>  

二,在Spring-config.xml中引入以上新建的配置文件,配置如下:

[html]  view plain  copy
  1. <import resource="classpath:Spring-freemarker.xml" />  

三,修改Spring-servlet.xml,配置freeMarker视图解析器,如下:

[html]  view plain  copy
  1. <!-- 配置freeMarker视图解析器 -->      
  2.     <bean id="viewResolver" class="org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver">  
  3.         <property name="contentType" value="text/html; charset=UTF-8" />  
  4.         <property name="suffix" value=".ftl" />  
  5.     </bean>  
四,测试,新建hello.ftl页面,代码如下:

[html]  view plain  copy
  1. <!DOCTYPE html>  
  2. <html>  
  3. <head>  
  4. <meta charset="UTF-8">  
  5. <title>Insert title here</title>  
  6. </head>  
  7. <body>  
  8. [#--从Attribute中获取参数--]  
  9. <h1>${msg}</h1>  
  10.   
  11. [#--判断句式--]   
  12. <h1>${(1 == 1)?string("yes", "no")}</h1>  
  13.   
  14. [#--集合遍历--]  
  15. <ul>  
  16. [#list list as item]  
  17. <li>${item}</li>  
  18. [/#list]  
  19. </ui>  
  20.   
  21. [#if msg=='hello']  
  22. <h1>say hello</h1>  
  23. [#else]  
  24. <h1>say goodbye</h1>  
  25. [/#if]  
  26.   
  27. </body>  
  28. </html>  
这里用的了[#if],[#list] 指令,其他freemarker常用指令,大家可以百度学习。

五,新建测试Controller,FreemarkerController,代码如下:

[java]  view plain  copy
  1. package com.maven.web.controller;  
  2.   
  3. import java.util.ArrayList;  
  4. import java.util.List;  
  5.   
  6. import org.springframework.stereotype.Controller;  
  7. import org.springframework.ui.Model;  
  8. import org.springframework.web.bind.annotation.RequestMapping;  
  9. import org.springframework.web.bind.annotation.RequestMethod;  
  10.   
  11. @Controller  
  12. @RequestMapping("/freemarker")  
  13. public class FreemarkerController {  
  14.   
  15.     @RequestMapping(value="/hello",method=RequestMethod.GET)  
  16.     public String sayHello(Model model){  
  17.         String msg = "Hello World";  
  18.         List<String> list = new ArrayList<String>(3);  
  19.         list.add("a");  
  20.         list.add("b");  
  21.         list.add("c");  
  22.         model.addAttribute("msg", msg);  
  23.         model.addAttribute("list", list);  
  24.         return "hello";  
  25.     }  
  26.       
  27. }  
六,启动tomcat,访问测试:


***************************************************************

单独集成freemarker演示到此结束,下面重点来看shiro集成。

一,添加Spring-shiro.xml配置文件,如下:

[html]  view plain  copy
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <beans xmlns="http://www.springframework.org/schema/beans"  
  3.        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
  4.        xmlns:p="http://www.springframework.org/schema/p"  
  5.        xsi:schemaLocation="http://www.springframework.org/schema/beans   
  6.        http://www.springframework.org/schema/beans/spring-beans-4.0.xsd">  
  7.       
  8.     <!-- Shiro主过滤器的拦截 -->  
  9.     <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">  
  10.         <!-- 权限管理器 -->  
  11.         <property name="securityManager" ref="securityManager" />  
  12.         <!-- 登录地址 -->  
  13.         <property name="loginUrl" value="/template/login.ftl" />  
  14.         <!-- 登录后跳转到业务页面 -->  
  15.         <property name="successUrl" value="/template/main.ftl" />  
  16.         <!-- 错误页面 -->  
  17.         <property name="unauthorizedUrl" value="/template/error.ftl" />  
  18.         <!-- 鉴权过滤器 -->  
  19.         <property name="filters">  
  20.             <map>  
  21.                 <entry key="logout" value-ref="logoutFilter" />  
  22.                 <entry key="authc" value-ref="myAuthenticationFilter" />  
  23.             </map>  
  24.         </property>   
  25.         <!-- 权限配置 -->  
  26.         <property name="filterChainDefinitions">  
  27.             <value>  
  28.                  <!-- 对静态资源不需要进行认证 -->    
  29.                 /static/** = anon  
  30.                 /tags/** = anon  
  31.                 <!-- 登录退出不需要验证 -->  
  32.                 /login/**=anon    
  33.                 /logout = logout  
  34.                 <!-- 对所有url都需要进行认证 -->    
  35.                 /** = authc  
  36.             </value>  
  37.         </property>  
  38.     </bean>  
  39.       
  40.     <!-- 配置权限管理器 -->  
  41.     <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">  
  42.         <!-- 缓存管理器 -->   
  43.         <property name="cacheManager" ref="cacheManager" />  
  44.         <!-- 我们自定义的realm -->  
  45.         <property name="realm" ref="myRealm" />  
  46.     </bean>  
  47.       
  48.     <!-- 自定义的Realm,若有多个Realm,可使用'realms'属性代替 -->    
  49.     <bean id="myRealm" class="com.maven.web.shiro.MyRealm" />  
  50.       
  51.     <!-- 重写的认证filter-->  
  52.     <bean id="myAuthenticationFilter" class="com.maven.web.shiro.MyAuthenticationFilter" />  
  53.       
  54.     <!-- 使用shiro提供的logout filter -->  
  55.     <bean id="logoutFilter" class="org.apache.shiro.web.filter.authc.LogoutFilter">  
  56.         <property name="redirectUrl" value="/template/login.ftl" />  
  57.     </bean>  
  58.       
  59.     <!-- shiro 缓存管理 -->    
  60.     <bean id="cacheManager" class="org.apache.shiro.cache.MemoryConstrainedCacheManager" />  
  61.       
  62.     <!-- Shiro生命周期处理器 -->  
  63.     <bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor" />  
  64.           
  65. </beans>  
*********************************************************************************************************************

这里需要注意:

默认的shiro authc 认证参数是username+password,我这里重写了认证方法,改为认证phone+password,

如果没有此需要的,去掉上面配置文件中的以下配置即可,采用默认过滤器




同理,其他anon,logout过滤器也可以重写,还可以自定义过滤器,这些大家可以根据需要来实现,不多介绍。


二,在web.xml 中添加shiro核心过滤器,配置如下:

[html]  view plain  copy
  1. <!-- 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>  

三,在Spring-config.xml中引入shiro配置文件,配置如下:

[html]  view plain  copy
  1. <import resource="classpath:Spring-shiro.xml" />  

四,重写自己的Realm授权+认证方法,在此之前,先实现我们需要的认证参数。

(一) 新建MyAuthenticationToken继承UsernamePasswordToken,添加我们需要的phone属性,代码如下:

(如果不需要自定义属性就不需要写这一步了,直接用UsernamePasswordToken即可)

[java]  view plain  copy
  1. package com.maven.web.shiro;  
  2.   
  3. import org.apache.shiro.authc.UsernamePasswordToken;  
  4.   
  5. /** 
  6.  * 重新token,对用户名的认证改为手机号 
  7.  * @author Administrator 
  8.  * 
  9.  */  
  10. public class MyAuthenticationToken extends UsernamePasswordToken{  
  11.   
  12.     private static final long serialVersionUID = 1425855488092920451L;  
  13.       
  14.     /** 手机号 */  
  15.     private String phone;  
  16.   
  17.     public MyAuthenticationToken(String phone, String password, boolean rememberMe, String host) {  
  18.         super(null, password, rememberMe, host);  
  19.         this.phone = phone;  
  20.     }  
  21.   
  22.     /** 默认是返回用户名,改写返回手机号 */  
  23.     @Override  
  24.     public Object getPrincipal() {  
  25.         return phone;  
  26.     }  
  27.   
  28.     @Override  
  29.     public void clear() {  
  30.         super.clear();  
  31.         phone = null;  
  32.     }  
  33.   
  34.     public String getPhone() {  
  35.         return phone;  
  36.     }  
  37.   
  38.     public void setPhone(String phone) {  
  39.         this.phone = phone;  
  40.     }  
  41.       
  42.       
  43.   
  44. }  
(二) 新建MyAuthenticationFilter继承FormAuthenticationFilter,实现用户认证,代码如下:
[java]  view plain  copy
  1. package com.maven.web.shiro;  
  2.   
  3. import javax.servlet.ServletRequest;  
  4. import javax.servlet.ServletResponse;  
  5.   
  6. import org.apache.shiro.authc.AuthenticationToken;  
  7. import org.apache.shiro.web.filter.authc.FormAuthenticationFilter;  
  8. import org.apache.shiro.web.util.WebUtils;  
  9.   
  10. /** 
  11.  * 重写token认证 
  12.  * @author Administrator 
  13.  * 
  14.  */  
  15. public class MyAuthenticationFilter extends FormAuthenticationFilter{  
  16.   
  17.     public static final String DEFAULT_PHONE_PARAM = "phone";  
  18.       
  19.     private String phoneParam = DEFAULT_PHONE_PARAM;  
  20.       
  21.     public MyAuthenticationFilter(){  
  22.         setFailureKeyAttribute(DEFAULT_ERROR_KEY_ATTRIBUTE_NAME);  
  23.     }  
  24.       
  25.     @Override  
  26.     protected AuthenticationToken createToken(ServletRequest request, ServletResponse response) {  
  27.         String phone = getPhone(request);  
  28.         String password = getPassword(request);  
  29.         boolean rememberMe = isRememberMe(request);  
  30.         String host = getHost(request);   
  31.           
  32.         return new com.maven.web.shiro.MyAuthenticationToken(phone,password,rememberMe,host);  
  33.     }  
  34.   
  35.     public String getPhoneParam() {  
  36.         return phoneParam;  
  37.     }  
  38.   
  39.     public void setPhoneParam(String phoneParam) {  
  40.         this.phoneParam = phoneParam;  
  41.     }  
  42.   
  43.     protected String getPhone(ServletRequest request) {  
  44.         return WebUtils.getCleanParam(request, getPhoneParam());  
  45.     }   
  46.       
  47. }  
(三) 新建自己的Realm类,MyRealm 继承AuthorizingRealm,代码如下:

[java]  view plain  copy
  1. package com.maven.web.shiro;  
  2.   
  3. import java.util.ArrayList;  
  4. import java.util.Iterator;  
  5. import java.util.List;  
  6.   
  7. import javax.annotation.Resource;  
  8.   
  9. import org.apache.shiro.authc.AuthenticationException;  
  10. import org.apache.shiro.authc.AuthenticationInfo;  
  11. import org.apache.shiro.authc.AuthenticationToken;  
  12. import org.apache.shiro.authc.DisabledAccountException;  
  13. import org.apache.shiro.authc.IncorrectCredentialsException;  
  14. import org.apache.shiro.authc.SimpleAuthenticationInfo;  
  15. import org.apache.shiro.authz.AuthorizationInfo;  
  16. import org.apache.shiro.authz.SimpleAuthorizationInfo;  
  17. import org.apache.shiro.realm.AuthorizingRealm;  
  18. import org.apache.shiro.subject.PrincipalCollection;  
  19.   
  20. import com.maven.web.entity.MenuChild;  
  21. import com.maven.web.entity.RoleInfo;  
  22. import com.maven.web.entity.UserInfo;  
  23. import com.maven.web.exception.AuthenticateException;  
  24. import com.maven.web.mapper.MenuChildMapper;  
  25. import com.maven.web.mapper.RoleInfoMapper;  
  26. import com.maven.web.service.impl.UserService;  
  27.   
  28. public class MyRealm extends AuthorizingRealm{  
  29.       
  30.     @Resource  
  31.     private UserService userService;  
  32.       
  33.     @Resource  
  34.     private MenuChildMapper menuChildMapper;  
  35.       
  36.     @Resource  
  37.     private RoleInfoMapper roleInfoMapper;  
  38.       
  39.     public MyRealm() {  
  40.         setAuthenticationTokenClass(AuthenticationToken.class);  
  41.     }  
  42.   
  43.     /** 
  44.      * 重写认证方法 
  45.      */  
  46.     @Override  
  47.     protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {  
  48.         UserInfo userInfo = null;  
  49.         if(token instanceof MyAuthenticationToken){  
  50.             MyAuthenticationToken myToken = (MyAuthenticationToken) token;  
  51.             String phone = myToken.getPhone();  
  52.             String password = new String(myToken.getPassword());  
  53.             try {  
  54.                 userInfo = userService.getUserInfoNyPhone(phone,password);  
  55.             } catch (AuthenticateException e){  
  56.                 throw new IncorrectCredentialsException(e);  
  57.             }  
  58.               
  59.             if (null == userInfo) {  
  60.                 throw new IncorrectCredentialsException("账号或密码错误!");  
  61.             }  
  62.               
  63.             if (!"0".equals(userInfo.getStatus())) {  
  64.                 throw new DisabledAccountException("帐号"+myToken.getPrincipal()+"已失效!");  
  65.             }  
  66.               
  67.             //比对成功则返回authcInfo  
  68.             AuthenticationInfo authcInfo = new SimpleAuthenticationInfo(userInfo, userInfo.getPassword().toCharArray(),this.getName());    
  69. //          this.setSession("currentUser", userInfo);    
  70.             return authcInfo;   
  71.         }  
  72.         return null;  
  73.     }  
  74.       
  75.     /** 
  76.      * 为认证成功的用户授权,然后就可以调用subject.hasRole等方法进行逻辑判断 
  77.      */  
  78.     @Override  
  79.     protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {  
  80.         //认证通过后会将需要的身份信息放到SimpleAuthenticationInfo中返回,这是是获取到其中的principal对象  
  81.         Iterator<?> iterator = principals.fromRealm(getName()).iterator();  
  82.         if (iterator.hasNext()) {  
  83.             UserInfo userInfo = (UserInfo) iterator.next();  
  84.             if (null != userInfo) {  
  85.                 List<String> roleList = new ArrayList<String>();  
  86.                 List<String> permissionList = new ArrayList<String>();  
  87.                 //查询用户角色  
  88.                 RoleInfo userRole = roleInfoMapper.selectByUserId(userInfo.getId());  
  89.                 if(null !=userRole){  
  90.                     roleList.add(userRole.getRoleName());  
  91.                     List<MenuChild> roleMenus = menuChildMapper.getMenuChildByRoleId(userRole.getId());  
  92.                     if(null !=roleMenus){  
  93.                         for(MenuChild menu:roleMenus){  
  94.                             permissionList.add(menu.getMenuName());  
  95.                         }  
  96.                     }  
  97.                 }  
  98.                   
  99.                 //为用户添加权限,角色  
  100.                 SimpleAuthorizationInfo simpleAuthorInfo = new SimpleAuthorizationInfo();  
  101.                 simpleAuthorInfo.addRoles(roleList);  
  102.                 simpleAuthorInfo.addStringPermissions(permissionList);  
  103.                 return simpleAuthorInfo;  
  104.             }  
  105.         }  
  106.           
  107.         return null;  
  108.     }  
  109.   
  110.     /**  
  111.      * 将一些数据放到ShiroSession中,以便于其它地方使用  
  112.      * @see  比如Controller,使用时直接用HttpSession.getAttribute(key)就可以取到  
  113.      * 也可以直接从subject的身份对象中取 
  114.      */    
  115.    /* private void setSession(Object key, Object value){   
  116.         Subject currentUser = SecurityUtils.getSubject();   
  117.         if(null != currentUser){   
  118.             Session session = currentUser.getSession();   
  119.             System.out.println("Session默认超时时间为[" + session.getTimeout() + "]毫秒");   
  120.             if(null != session){   
  121.                 session.setAttribute(key, value);   
  122.             }   
  123.         }   
  124.     }*/  
  125.   
  126. }  
*******************************************************************************************************************

这里说明一下:

认证方法,是对用户在登录页面提交的信息做校验,登录成功才会跳转到主页。

授权方法,用户登录成功后可以根据用户信息查找相关角色,权限,存储到授权对象中。

以后就可以通过Java代码,shiro标签等,获取当前用户的角色,权限,进行模块功能分配等等。下面会演示。


五,用户登录

(一) 新建登录页面,login.ftl,代码如下:

[html]  view plain  copy
  1. <!DOCTYPE html>  
  2. <html>  
  3. <head>  
  4. <meta charset="UTF-8">  
  5. <title>Insert title here</title>  
  6. </head>  
  7. <body>  
  8. <form action="/com.maven.web/login/login" method="post" id="form">  
  9. <article>手机号:</article>  
  10. <input type="text" name="phone"/>  
  11. <article>密码:</article>  
  12. <input type="password" name="password"/>  
  13. <br/>  
  14. <br/>  
  15. <input type="submit" value="登录" />  
  16. <br/>  
  17. </form>  
  18. <span style="color:red">${msg}</span>  
  19. </body>  
  20. </html>  

(二) 新建 LoginContoller,代码如下:

[java]  view plain  copy
  1. package com.maven.web.controller;  
  2.   
  3. import javax.servlet.http.HttpServletRequest;  
  4.   
  5. import org.apache.shiro.SecurityUtils;  
  6. import org.apache.shiro.authc.AuthenticationException;  
  7. import org.apache.shiro.subject.Subject;  
  8. import org.slf4j.Logger;  
  9. import org.springframework.stereotype.Controller;  
  10. import org.springframework.ui.Model;  
  11. import org.springframework.web.bind.annotation.RequestMapping;  
  12. import org.springframework.web.bind.annotation.RequestMethod;  
  13.   
  14. import com.maven.web.entity.UserInfo;  
  15. import com.maven.web.shiro.MyAuthenticationToken;  
  16. import com.maven.web.util.LoggerUtils;  
  17.   
  18. @Controller  
  19. @RequestMapping("/login")  
  20. public class LoginController {  
  21.     private final Logger logger = LoggerUtils.getLogger("LoginController");  
  22.   
  23.     /** 
  24.      * 基于手机号和密码的身份认证 
  25.      * @param userInfo 
  26.      * @param model 
  27.      * @param request 
  28.      * @return 
  29.      */  
  30.     @RequestMapping(value="/login",method=RequestMethod.POST)  
  31.     public String checkLogin(UserInfo userInfo,Model model,HttpServletRequest request){  
  32.   
  33.         logger.debug("userInfo", userInfo);;  
  34.           
  35.         MyAuthenticationToken token = new MyAuthenticationToken(userInfo.getPhone(), userInfo.getPassword(), truenull);  
  36.         Subject subject = SecurityUtils.getSubject();  
  37.         try {  
  38.             subject.login(token);//会到自定义的Realm中进行验证返回  
  39.             if(subject.isAuthenticated()){  
  40.                 return "redirect:/menu/list";  
  41.             }else{  
  42.                 token.clear();  
  43.             }  
  44.         }catch(AuthenticationException e){  
  45.             model.addAttribute("msg",e.getMessage());  
  46.         }  
  47.         return "login";  
  48.     }  
  49.       
  50.      /**  
  51.      * 用户登出  
  52.      */    
  53.     @RequestMapping("/logout")    
  54.     public String logout(){    
  55.          SecurityUtils.getSubject().logout();    
  56.          return "login";    
  57.     }   
  58. }  

(三) 新建登录成功页面,main.ftl,代码如下:

[html]  view plain  copy
  1. <!DOCTYPE html>  
  2. <html>  
  3. <head>  
  4. <meta charset="UTF-8">  
  5. <title>Insert title here</title>  
  6. </head>  
  7. <body>  
  8.     <span>菜单栏</span>  
  9.     <ul>  
  10.         [#list menus as menu]  
  11.         <li><a href="#">${menu.menuParent.menuName}</a></li>  
  12.         <li>  
  13.             <ul>  
  14.                 [#list menu.menuChilds as menuChild]  
  15.                 <li><a href=${menuChild.menuUrl}>${menuChild.menuName}</a></li>   
  16.                 [/#list]  
  17.             </ul>  
  18.         </li>   
  19.         [/#list]  
  20.     </ul>  
  21.     <span>${msg}</span>  
  22.     <br/>  
  23.     <div>  
  24.     [@shiro.hasRole name="管理员"]  
  25.     <span>角色是管理员才能看到此信息</span>  
  26.     [/@shiro.hasRole]  
  27.     </div>  
  28.     <a href="/com.maven.web/login/logout">logout</a>  
  29. </body>  
  30. </html>  
(四) 新建MenuController,动态查询菜单权限返回主页面main.ftl,代码如下:
[java]  view plain  copy
  1. package com.maven.web.controller;  
  2.   
  3. import java.util.ArrayList;  
  4. import java.util.List;  
  5.   
  6. import javax.annotation.Resource;  
  7.   
  8. import org.apache.shiro.SecurityUtils;  
  9. import org.apache.shiro.subject.Subject;  
  10. import org.springframework.stereotype.Controller;  
  11. import org.springframework.ui.Model;  
  12. import org.springframework.web.bind.annotation.RequestMapping;  
  13. import org.springframework.web.bind.annotation.RequestMethod;  
  14.   
  15. import com.maven.web.entity.MenuChild;  
  16. import com.maven.web.entity.MenuParent;  
  17. import com.maven.web.mapper.MenuChildMapper;  
  18. import com.maven.web.mapper.MenuParentMapper;  
  19. import com.maven.web.vo.Menu;  
  20.   
  21. @Controller  
  22. @RequestMapping("/menu")  
  23. public class MenuController {  
  24.       
  25.     @Resource  
  26.     private MenuParentMapper menuParentMapper;   
  27.       
  28.     @Resource  
  29.     private MenuChildMapper menuChildMapper;   
  30.       
  31.     @RequestMapping(value="/list",method=RequestMethod.GET)  
  32.     public String listMenu(Model model){  
  33.         List<Menu> menus = new ArrayList<Menu>();  
  34.         List<MenuParent> parents = menuParentMapper.getMenuParentList();  
  35.         if(parents!=null && !parents.isEmpty()){  
  36.             for(MenuParent parent:parents){  
  37.                 Menu menu = new Menu();  
  38.                 menu.setMenuParent(parent);  
  39.                 List<MenuChild> childs = menuChildMapper.getMenuChildByPid(parent.getId());  
  40.                 if(childs!=null && !childs.isEmpty()){  
  41.                     menu.setMenuChilds(childs);  
  42.                 }  
  43.                 menus.add(menu);  
  44.             }  
  45.         }  
  46.         model.addAttribute("menus",menus);  
  47.         Subject subject = SecurityUtils.getSubject();  
  48.         if(subject.hasRole("管理员")){  
  49.             model.addAttribute("msg","这里是管理员私人信息!");  
  50.         }  
  51.         return "main";  
  52.     }  
  53.       
  54. }  

六,启动tomcat,测试:

这里先给大家看一下我数据库的用户信息:


启动访问,未登录会跳转到登录页面

测试一:错误用户信息



测试二:新注册用户状态为未激活



测试三:管理员登录



测试四:普通用户登录



*******************************************************************************************************

这里请大家注意,管理员登录成功后可以看到红色框和黄色框两条信息,普通用户登录后看不到。

(1) 红色框信息:

这是因为在MenuController中做了角色判断,注意代码片段:

[java]  view plain  copy
  1. Subject subject = SecurityUtils.getSubject();  
  2.         if(subject.hasRole("管理员")){  
  3.             model.addAttribute("msg","这里是管理员私人信息!");  
  4.         }  

(2) 黄色框信息:

这是因为在main.ftl页面中使用了shiro标签,注意代码片段:

[html]  view plain  copy
  1. <div>  
  2.     [@shiro.hasRole name="管理员"]  
  3.     <span>角色是管理员才能看到此信息</span>  
  4.     [/@shiro.hasRole]  
  5.     </div>  
********************************************************************************************************
接下来说明shiro标签的使用:

(一) 在freemarker中需要先引入shiro-freemarker-tags-0.1-SNAPSHOT.jar,本例已经添加到pom.xml文件中,

大家可以下载源码,在lib中找到jar包添加到本地,也可以到网上下载,下面会贴出链接。


(二) 新建CustomFreeMarkerConfigurer 继承FreeMarkerConfigurer,代码如下:

[java]  view plain  copy
  1. package com.maven.web.template;  
  2.   
  3. import java.io.IOException;  
  4.   
  5. import org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer;  
  6.   
  7. import com.jagregory.shiro.freemarker.ShiroTags;  
  8.   
  9. import freemarker.template.TemplateException;  
  10.   
  11. /** 
  12.  * 编写自己的freemarker配置 
  13.  * @author Administrator 
  14.  * 
  15.  */  
  16. public class CustomFreeMarkerConfigurer extends FreeMarkerConfigurer{  
  17.       
  18.   
  19.     /** 
  20.      * 重写导入shiro标签 
  21.      */  
  22.     @Override  
  23.     public void afterPropertiesSet() throws IOException, TemplateException {  
  24.         super.afterPropertiesSet();  
  25.         this.getConfiguration().setSharedVariable("shiro"new ShiroTags());  
  26.     }  
  27. }  
(三) 修改Spring-freemarker.xml配置文件,改成自定义的CustomFreeMarkerConfigurer



关于shiro标签与freemarker的整合,大家可以跳转链接学习:http://blog.csdn.net/lingyundouer/article/details/50487459


如果使用默认的authc认证,只需要将代码中MyAuthenticationToken替换成UsernamePasswordToken,

然后获取到的phone参数替换成username就可以,其他都是一样的。

以上就介绍完毕了,可能有所遗漏,大家可以下载源码参考:http://pan.baidu.com/s/1dFilb6h

猜你喜欢

转载自blog.csdn.net/qq_27676247/article/details/74280158