shiro+Thymeleaf整合教程

1.web.xml

<?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" id="WebApp_ID" version="3.0">

  <display-name>XZDataReport</display-name>

 

 

 

  <context-param>

    <param-name>contextConfigLocation</param-name>

    <param-value>classpath:ApplicationContext-*.xml</param-value>

  </context-param>

  <listener>

    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>

  </listener>

  

  

  <!--配置 SpringMVC -->

  <servlet>

    <servlet-name>springMvc</servlet-name>

    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>

    <init-param>

      <param-name>contextConfigLocation</param-name>

      <param-value>classpath:SpringMvc.xml</param-value>

    </init-param>

    <load-on-startup>1</load-on-startup>

  </servlet>

  <servlet-mapping>

    <servlet-name>springMvc</servlet-name>

    <url-pattern>/*</url-pattern>

  </servlet-mapping>

 

  <!--配置thymeleaf   不然404传不到给Controller -->

  <!--   <servlet-mapping>

        <servlet-name>springMvc</servlet-name>

        <url-pattern>*.html</url-pattern>

    </servlet-mapping>   -->

  

 

  <!-- 字符编码 -->

  <filter>

    <filter-name>CharacterEncodingFilter</filter-name>

    <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>

    <init-param>

      <param-name>encoding</param-name>

      <param-value>utf-8</param-value>

    </init-param>

  </filter>

  <filter-mapping>

    <filter-name>CharacterEncodingFilter</filter-name>

  <url-pattern>/*</url-pattern>

  </filter-mapping>

  

  

    <!-- 添加 Shiro 相关配置 -->

    <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> 

    <!--  去掉 jsessionid  -->

<session-config>

    <tracking-mode>COOKIE</tracking-mode>

</session-config>

</web-app>

 

2.项目目录结构

 

 

SpringMvc.xml

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"

xmlns:context="http://www.springframework.org/schema/context"

xmlns:dubbo="http://code.alibabatech.com/schema/dubbo" xmlns:mvc="http://www.springframework.org/schema/mvc"

xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd

        http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd

        http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd

        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">

    

 

    

    <!-- @Controller注解扫描 -->

    <context:component-scan base-package="com.syiaas.controller"></context:component-scan>

    <!-- 配置注解驱动 -->

<mvc:annotation-driven />

<!-- 资源映射 -->

<!-- 静态资源访问 -->  

<mvc:resources mapping="/css/**" location="/WEB-INF/css/"/>

 

   <!-- 使用thymeleaf解析 -->

    <bean id="templateResolver"

          class="org.thymeleaf.spring4.templateresolver.SpringResourceTemplateResolver">

        <property name="prefix" value="/WEB-INF/views/" />

        <property name="suffix" value=".html" />

        <property name="templateMode" value="HTML" />

        <property name="cacheable" value="false" />

        <property name="characterEncoding" value="UTF-8"/><!--不加会乱码-->

    </bean>

    <bean id="templateEngine"

          class="org.thymeleaf.spring4.SpringTemplateEngine">

        <property name="templateResolver" ref="templateResolver" />

        <!-- 支持html页面的shiro标签 -->

        <property name="additionalDialects">

    <set>

      <bean class="at.pollux.thymeleaf.shiro.dialect.ShiroDialect"/>

    </set>

       </property> 

    </bean>

    <bean class="org.thymeleaf.spring4.view.ThymeleafViewResolver">

        <property name="templateEngine" ref="templateEngine" />

        <!--解决中文乱码-->

        <property name="characterEncoding" value="UTF-8"/>

    </bean>

   

  

<!-- 定义文件上传解析器 -->

<bean id="multipartResolver"

class="org.springframework.web.multipart.commons.CommonsMultipartResolver">

<!-- 设定默认编码 -->

<property name="defaultEncoding" value="UTF-8"></property>

<!-- 设定文件上传的最大值5MB,5*1024*1024 -->

<property name="maxUploadSize" value="5242880"></property>

</bean>

</beans>

 

ApplicationContext-shiro.xml

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"

       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

       xmlns:context="http://www.springframework.org/schema/context"

       xmlns:mvc="http://www.springframework.org/schema/mvc"

       xsi:schemaLocation="

        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd

        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd

        http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd">

     <!-- 配置filter  -->

    <!-- 此bean的id 要被web.xml引用,和web.xml中的filtername同名 -->

    <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">

        <property name="securityManager" ref="securityManager"/>

        <property name="loginUrl" value="login.html" /> <!-- 没有认证返回地址 -->

        <property name="unauthorizedUrl" value="403.html" /> <!-- 没有授权返回地址 -->

        <property name="filterChainDefinitions">

            <!-- 

               **代表任意子目录    /user/** = authc,roles[admin]

               anon 不需要认证就可以访问

               authc 需要认证才能访问

            -->

            <value>          

            /login.html = anon

            /subLogin = anon

            <!-- 退出拦截 -->

            /logout = logout

            /* = authc

            </value>

        </property>

    </bean>

       <!-- 第一步:创建securityManager对象 -->

    <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">

        <!-- 引用自定义的realm -->

        <property name="realm" ref="realm"/>

    </bean>

    <!--第二步 自定义认证授权realm -->

    <bean id="realm" class="com.syiaas.shiro.realm.AuthRealm">

        <!-- 引用盐值加密 -->

        <property name="credentialsMatcher" ref="credentialsMatcher"></property>

    </bean>

    <!-- 设置盐值加密  加密的方式以及次数 --> 

    <bean class="org.apache.shiro.authc.credential.HashedCredentialsMatcher" id="credentialsMatcher">

       <property name="hashAlgorithmName" value="md5"></property>

       <property name="hashIterations" value="1"></property>

    </bean>

</beans>

package com.syiaas.shiro.realm;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.crypto.hash.Md5Hash;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;


//继承 AuthorizingRealm 
public class AuthRealm extends AuthorizingRealm {

    
    Map<String,String> userMap=new HashMap<String, String>();
    
    {
        
        //123456
        userMap.put("Mark", "283538989cef48f3d7d8a1c1bdf2008f");
        //设置自定义realm名称
        super.setName("authRealm");
        
        
    }
    
    
    //第二步:授权
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        //首先从认证信息中获取到用户
        String userName=(String) principals.getPrimaryPrincipal();
        System.out.println("授权 userName="+userName);
        //根据用户查询对应的角色
        //set集合 用于存储无序(存入和取出的顺序不一定相同)元素,值不能重复。
        Set<String> roles=getRolesByUserName(userName);
        Set<String> permissions=getPermissionsByUserName(userName);
        
        //创建SimpleAuthorizationInfo 用于存储角色和权限
        SimpleAuthorizationInfo simpleAuthorizationInfo=new SimpleAuthorizationInfo();
        
        simpleAuthorizationInfo.setRoles(roles);
        simpleAuthorizationInfo.setStringPermissions(permissions);
        
        return simpleAuthorizationInfo;
    }

    
    //模拟从数据库中或者缓冲中获取用户信息对应的角色信息
    private Set<String> getRolesByUserName(String userName) {
        Set<String> sets=new HashSet<String>();
        sets.add("admin");
        sets.add("user");
        return sets;
    }

    //模拟从数据库中或者缓冲中获取用户信息对应的权限信息
        private Set<String> getPermissionsByUserName(String userName) {
            Set<String> sets=new HashSet<String>();
            sets.add("user:delete");
            sets.add("user:add");
            return sets;            
        }

    //第一步:认证
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
    
        //1.从主体传过来的认证信息中,获得用户名
        String userName=(String) token.getPrincipal();
        //2.通过用户名到数据库中获取凭证
        String password=getPasswordByUserName(userName);
        
        System.out.println("认证  userName="+userName+"====password=="+password);
        
        if(password==null){
            return null;
        }
        //若存在构造一个用户认证信息实体类 SimpleAuthenticationInfo 参数(用户名,密码,realmName)
        SimpleAuthenticationInfo authenticationInfo=new SimpleAuthenticationInfo("Mark",password,"authRealm");
        //设置盐值
        authenticationInfo.setCredentialsSalt(ByteSource.Util.bytes("Mark"));
        return authenticationInfo;
    }
    //模拟从数据库或缓冲中查询账号所对应的密码
    private String getPasswordByUserName(String userName) {
        return userMap.get(userName);
        
    }

    
//    @Test
//    public void getMd5(){
//        //参数 密码+盐值
//        Md5Hash md5Hash=new Md5Hash("123456","Mark");
//        System.out.println(md5Hash);
//        
//    }
    
}

package com.syiaas.controller;
import java.text.ParseException;
import java.util.List;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.ExcessiveAttemptsException;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import com.syiaas.dao.ExhibitionInfoDao;
import com.syiaas.dao.WuserDao;
import com.syiaas.pojo.Pie;
import com.syiaas.pojo.Shoes;
import com.syiaas.pojo.Userinfo;
import com.syiaas.utils.Constants;
import com.syiaas.utils.DataSourceHolder;

@Controller
public class TestController {
    
    
    @Autowired
    private ExhibitionInfoDao exhibitionInfoDao;
    
    

    @Autowired
    private WuserDao wuserDao;
    
    @RequestMapping(value = "/thymeleaf", method=RequestMethod.GET)
    public  String  thymeleaf(Model model) throws Exception {
        model.addAttribute("test","helloworld");
        return "demo";
    }
    
    @RequestMapping(value = { "/saveProduct" }, method = RequestMethod.POST)
    public String saveprodcut(Model model, @ModelAttribute(value = "shoe") Shoes shoe) throws ParseException {
      
        System.out.println(shoe.getName()+"==="+shoe.getAvailableFrom()+"==="+shoe.getPrice());
        return "footer";
    }
    
    //跳转登录页
//    @RequestMapping(value = "/login", method=RequestMethod.GET)
//    public  String  login(Model model) throws Exception {
//      
//        return "login";
//    }
    
    
    //测试shiro
     @RequestMapping(value="/subLogin",method=RequestMethod.POST,produces = "application/json; charset=UTF-8")
     //@ResponseBody
     public  String subLogin(Model model,Userinfo user){
         
         System.out.println("name="+user.getUsername()+"===password="+user.getPassword());
         
         //1.得到Subject及获取到前端页面输入的用户名/密码身份验证Token(即用户身份/凭证)
        Subject subject=SecurityUtils.getSubject();
        UsernamePasswordToken token=new UsernamePasswordToken(user.getUsername(),user.getPassword());
        
//        try {     
//           
//            //2、登录,即身份验证
//            subject.login(token);
//            System.out.println(subject.isAuthenticated());
//            //是否具备某一个角色
//            System.out.println("角色=="+subject.hasRole("admin"));
//         } catch (AuthenticationException e) {
//            //身份验证失败,返回登录页
//            System.out.println(e.getMessage());
//            //return e.getMessage();
//         }
//        
//        
//        return "demo";     
        String error = null;  
        try {  
            subject.login(token);  
            
        } catch (UnknownAccountException e) {  
            error = "用户名/密码错误";  
        } catch (IncorrectCredentialsException e) {  
            error = "用户名/密码错误";  
        } catch (ExcessiveAttemptsException e) {  
            // TODO: handle exception  
            error = "登录失败多次,账户锁定10分钟";  
        } catch (AuthenticationException e) {  
            // 其他错误,比如锁定,如果想单独处理请单独catch处理  
            error = "其他错误:" + e.getMessage();  
        }  
        
        if (error != null) {// 出错了,返回登录页面  
            model.addAttribute("error", error);  
            System.out.println("error=="+error);
            //return "login";  
        } else {// 登录成功  
            System.out.println(subject.isAuthenticated());
            return "demo";  
        }
        return null;  

     
        
     }
      
    

    
   
}
 

login.html

<html>

<head>

    <title>登录</title>

    <meta charset="UTF-8">

    <style type="text/css">

     .box{

        width: 300px;

        height: 300px;

     margin: 0 auto;

     }

     input{

     margin: 10px;

     }

    </style>

   

</head>

<body>

<div class="box">

    <form action="/DataAnalysisSystem/subLogin" method="post">

     

     用户名:<input type="text" name="username"><br>

     密码:<input type="password" name="password"><br>

  

     <input type="submit" value="登录">

    </form>

</div>

</body>

</html>

 

 

demo.html

<!DOCTYPE html>

<head>

  <title>ceshi</title>

 <html xmlns:th="http://www.thymeleaf.org"

      xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity4"  

      xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">    

  <meta http-equiv="content-type" content="txt/html; charset=utf-8" />

  <link rel="stylesheet" type="text/css" th:href="@{/css/index.css}"></link>  <!--到样式表的th:href链接-->

</head>

<body>

    <!--  <h2>算术表达式</h2>

     <form th:action="@{/saveProduct.html}" th:object="${shoe}" method="POST">

          <label for="firstName">产品名称:</label>

          <input type="text" name="name" value="" /><br/>

 

          <label for="firstName">有效日期:</label>

          <input type="text" name="availableFrom" /> <br/>        

 

          <label for="price">价格 (RMB):</label>

          <input type="text" name="price" size="10"/><br/>

 

          <input type="submit" value="提交"/>

    </form> -->

    

    <!-- 1 guest(游客) -->

    <shiro:guest>  

         您当前是游客,登录</a>

    </shiro:guest> 

     <hr>

    <!-- 2 user(已经登录,或者记住我登录)  -->

<shiro:user>  

           欢迎[<shiro:principal/>]登录,<a href="/DataAnalysisSystem/logout">退出</a>  

    </shiro:user>   

    <hr>

    <!-- 3 authenticated(已经认证,排除记住我登录的)  -->

    <shiro:authenticated>  

    用户[<shiro:principal/>]已身份验证通过  

    </shiro:authenticated>   

     <hr>

    <!-- 4 notAuthenticated(和authenticated相反)  用于识别是不是本次操作登录过的, -->

    <shiro:notAuthenticated>

  当前身份未认证(包括记住我登录的)

    </shiro:notAuthenticated> 

     <hr>

    <!--5 取到username-->

    <h1> welcome: <shiro:principal/></h1>

     <hr>

    <!-- 6.hasRole标签(判断是否拥有这个角色)  -->

    <shiro:hasRole name="admin">  

    用户[<shiro:principal/>]拥有角色admin<br/>  

    </shiro:hasRole>   

     <hr>

   <!--  7.hasAnyRoles标签(判断是否拥有这些角色的其中一个) -->

    <shiro:hasAnyRoles name="admin,user,member">  

       用户[<shiro:principal/>]拥有角色admin或user或member<br/>  

   </shiro:hasAnyRoles>   

      <hr>

  <!-- 8.lacksRole标签(判断是否不拥有这个角色) -->

  <shiro:lacksRole name="admin">  

      用户[<shiro:principal/>]不拥有admin角色

  </shiro:lacksRole>   

   <hr>

  <!-- 9.hasPermission标签(判断是否有拥有这个权限) -->

  <shiro:hasPermission name="user:add">  

用户[<shiro:principal/>]拥有user:add权限

  </shiro:hasPermission> 

   <hr>

  <!-- 10.lacksPermission标签(判断是否没有这个权限) --> 

  <shiro:lacksPermission name="user:add">  

用户[<shiro:principal/>]不拥有user:add权限

  </shiro:lacksPermission> 

</body>

</html>

 

 

 

转载于:https://my.oschina.net/shanesen/blog/1843035

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值