shiro标签只能在jsp和ftl页面文件中使用,无法在html文件中使用


shiro认证后的在jsp页面中的标签:
使用shiro标签就一定要搭配shiro框架使用,即一定要有自定义realm,因为shiro标签的内容就是自定义realm中认证的信息,以及授予的权利


步骤一:在pom.xml文件中导入依赖

 <spring.version>4.3.25.RELEASE</spring.version><shiro.version>1.2.2</shiro.version><dependencies><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.11</version></dependency><!-- 德鲁伊数据连接池 --><dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId><version>1.0.9</version></dependency><!--shiro相关依赖--><dependency><groupId>org.apache.shiro</groupId><artifactId>shiro-core</artifactId><version>${shiro.version}</version></dependency><dependency><groupId>org.apache.shiro</groupId><artifactId>shiro-web</artifactId><version>${shiro.version}</version></dependency><dependency><groupId>org.apache.shiro</groupId><artifactId>shiro-ehcache</artifactId><version>${shiro.version}</version></dependency><dependency><groupId>org.apache.shiro</groupId><artifactId>shiro-spring</artifactId><version>${shiro.version}</version></dependency><!--spring ioc/di--><dependency><groupId>org.springframework</groupId><artifactId>spring-core</artifactId><version>${spring.version}</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>${spring.version}</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-beans</artifactId><version>${spring.version}</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-expression</artifactId><version>${spring.version}</version></dependency><!-- spring - aop --><dependency><groupId>org.springframework</groupId><artifactId>spring-aop</artifactId><version>${spring.version}</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-aspects</artifactId><version>${spring.version}</version></dependency><dependency><groupId>aopalliance</groupId><artifactId>aopalliance</artifactId><version>1.0</version></dependency><dependency><groupId>org.aspectj</groupId><artifactId>aspectjweaver</artifactId><version>1.8.10</version></dependency><dependency><groupId>cglib</groupId><artifactId>cglib</artifactId><version>3.2.4</version></dependency><!-- spring tx--><dependency><groupId>org.springframework</groupId><artifactId>spring-tx</artifactId><version>${spring.version}</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-jdbc</artifactId><version>${spring.version}</version></dependency><!--web项目  --><dependency><groupId>javax.servlet</groupId><artifactId>javax.servlet-api</artifactId><version>3.1.0</version></dependency><dependency><groupId>javax.servlet.jsp</groupId><artifactId>jsp-api</artifactId><version>2.2</version></dependency><dependency><groupId>javax.servlet</groupId><artifactId>jstl</artifactId><version>1.2</version></dependency><!--spring整合web项目 --><dependency><groupId>org.springframework</groupId><artifactId>spring-web</artifactId><version>${spring.version}</version></dependency><!--springmvc --><dependency><groupId>org.springframework</groupId><artifactId>spring-webmvc</artifactId><version>${spring.version}</version></dependency><!-- json --><dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId><version>2.8.9</version></dependency><!-- 文件上传--><dependency><groupId>commons-fileupload</groupId><artifactId>commons-fileupload</artifactId><version>1.3.1</version></dependency><dependency><groupId>commons-io</groupId><artifactId>commons-io</artifactId><version>2.4</version></dependency><!--数据库相关 --><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>5.1.48</version></dependency><dependency><groupId>com.mchange</groupId><artifactId>c3p0</artifactId><version>0.9.5.2</version></dependency><dependency><groupId>org.mybatis</groupId><artifactId>mybatis</artifactId><version>3.4.5</version></dependency><!-- 缓存--><dependency><groupId>org.mybatis</groupId><artifactId>mybatis-ehcache</artifactId><version>1.0.0</version></dependency><dependency><groupId>net.sf.ehcache</groupId><artifactId>ehcache-core</artifactId><version>2.6.5</version></dependency><dependency><groupId>com.github.pagehelper</groupId><artifactId>pagehelper</artifactId><version>4.1.6</version></dependency><!-- mybatis整合spring  --><!-- https://mvnrepository.com/artifact/org.mybatis/mybatis-spring --><dependency><groupId>org.mybatis</groupId><artifactId>mybatis-spring</artifactId><version>1.3.2</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-context-support</artifactId><version>${spring.version}</version></dependency><dependency><groupId>com.yunpian.sdk</groupId><artifactId>yunpian-java-sdk</artifactId><version>1.2.7</version></dependency><!-- quartz --><dependency><groupId>org.springframework</groupId><artifactId>spring-context-support</artifactId><version>${spring.version}</version></dependency><dependency><groupId>com.yunpian.sdk</groupId><artifactId>yunpian-java-sdk</artifactId><version>1.2.7</version></dependency><!-- freemarker--><dependency><groupId>org.freemarker</groupId><artifactId>freemarker</artifactId><version>2.3.23</version></dependency></dependencies>

步骤二:在resources文件夹创建mybatis-config.xml配置文件

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN""http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration><!--给类起别名,默认是包下的类名首字母小写,后面字母不变就是它对应的别名。这个别名是给mapper文件省略类路径用的,如parameter、resultType等。基本类型mybatis已经七号别名了,因此只用管我们自建的实体类即可--><!--<typeAliases>&lt;!&ndash;<typeAlias type="com.entity.Student" alias="abc"></typeAlias>&ndash;&gt;<package name="com.qf.entity"></package></typeAliases>--><!--   &lt;!&ndash;展示出mapper文件中执行的sql语句的详细情况&ndash;&gt;<settings><setting name="logImpl" value="STDOUT_LOGGING"></setting></settings>--><!--插件写在plugins标签中,这里使用的就是分页插件--><plugins><plugin interceptor="com.github.pagehelper.PageHelper"><property name="dialect" value="mysql"/></plugin></plugins>
</configuration>

步骤三:在resouces下创建spring.xml配置文件

<?xml version="1.0" encoding="UTF-8"?>
<!--加p、tx、mvc、context命名空间-->
<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:tx="http://www.springframework.org/schema/tx"xmlns:mvc="http://www.springframework.org/schema/mvc"xmlns:context="http://www.springframework.org/schema/context"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvchttp://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/txhttp://www.springframework.org/schema/tx/spring-tx.xsd"><!--连接数据库,即创建数据库连接对象--><bean id="db" class="com.alibaba.druid.pool.DruidDataSource"><!--druid连接池包路径,其他两个连接池路径自己不知道可以网上找找。找到评论留言,分享给其他人吧--><property name="username" value="root"></property><!--你连接的数据库的用户名--><property name="password" value="root"></property><!--连接的数据库的密码--><property name="url" value="jdbc:mysql://localhost:3306/shiroweb"></property><!--连接的数据库的地址,此处的数据库名叫hospital--><property name="driverClassName" value="com.mysql.jdbc.Driver"></property><!--根据使用的数据库连接池以及数据库,找对应的连接池,三种连接池,druid,c3p0,dbcp。去百度吧。此处用的druid连接池和myql数据库--></bean><!--用context命名空间扫描注解包--><context:component-scan base-package="com"><!--扫描com包下的所有注解,这个com包是我们自定义的,我们创建的所有java类都放在该包下面,具体可见最下面的案例框架图的com包的位置--></context:component-scan><!--创建InternalResourceViewResolver视图解析器,注意下面这四行,尤其是前后缀的这两行会影响你在跳转页面的前后缀名,如return "/index.jsp",在使用这两句前后缀语句后,只需return "index"即可--><bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"><property name="prefix" value="/"></property> <!--return跳转页面时加前缀--><property name="suffix" value=".jsp"></property><!--加后缀--></bean><!--用MVC命名空间加注解驱动--><mvc:annotation-driven></mvc:annotation-driven><!--也是用于转换json必不可少的部分,另一个就是jackson包--><!--创建sqlsesion工厂,专门读取xml文件的--><bean id="factory" class="org.mybatis.spring.SqlSessionFactoryBean"><!--org.mybatis.spring.SqlSessionFactoryBean整合了mybatis和sring中的sqlsession--><property name="dataSource" ref="db"></property><!--将数据库连接赋进dataSource属性中--><property name="mapperLocations" value="classpath:mapper/*.xml"></property><!--mapper文件下的所有xml文件,不然创建一个扫描一个。此处*.xml爆红代表你mapper文件夹下还没创建xml文件--><property name="configLocation" value="classpath:mybatis-config.xml"></property><!--加载mybatis-config.xml配置文件--></bean><!--使用dao层实现类的时候,需要得到sqlSessionTemplate对象<bean class="org.mybatis.spring.SqlSessionTemplate"><constructor-arg index="0" ref="factory"></constructor-arg>&lt;!&ndash;将上面创建好的sqlsesion对象当成SqlSessionTemplate类的一个构造参数&ndash;&gt;</bean>--><!--6.省略dao实现类,扫描dao层的接口--><bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"><property name="basePackage" value="com.qf.dao"></property><property name="sqlSessionFactoryBeanName" value="factory" ></property></bean><bean id="tx" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><property name="dataSource" ref="db"></property></bean><tx:advice id="ad"  transaction-manager="tx" ></tx:advice><!--id必须起个名字--><!--8.配置静态资源,如果不写,静态资源无法显示在网页中。这段话是根据后缀名判断是否是静态资源的,这是其优势也是劣势。当controller的RequestMapping的请求地址为jsp时可测试出来。这是因为我们在web.xml文件中拦截了除jsp外的所有静态资源,而所有资源走的都是dispatcherservlet,然后dispatcherservlet会去找到handler,这也是为什么最终由RequestMapping请求路径后缀来判断--><mvc:default-servlet-handler></mvc:default-servlet-handler><!--freemarker解析器-->
<!--    <bean id="configruration"class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer">&lt;!&ndash; 模板放置的位置  / classpath resources&ndash;&gt;<property name="templateLoaderPath" value="/" />&lt;!&ndash;"/"表示ftl模板文件必须放在webapp下。ftl模板放在WEB-INF下的ftl文件夹下时value=/WEB-INF/ftl/,这表示ftl模板文件的位置&ndash;&gt;<property name="defaultEncoding" value="UTF-8" /></bean>&lt;!&ndash; 页面访问。访问ftl模板文件时,他会自动编译成html文件&ndash;&gt;<bean class="org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver">&lt;!&ndash;使用了freemarker视图解析器则必须把InternalResourceViewResolver这个springmvc的视图解析器去掉&ndash;&gt;<property name="contentType" value="text/html;charset=utf-8"/><property name="prefix" value="/" />&lt;!&ndash;前缀,此时省略也没事&ndash;&gt;<property name="suffix" value=".ftl" />&lt;!&ndash;controller层跳转的后缀,当index.ftl模板文件放在webapp下时访问路径:http://localhost:8080/index.ftl&ndash;&gt;</bean>--></beans>

步骤四:创建自定义realm,继承AuthorizingRealm类

package com.qf.realm;import com.qf.entity.User;
import com.qf.service.UserService;
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.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import javax.annotation.Resource;
import java.util.Set;//shiro 授权和赋予角色都是在自定义realm中完成的,这也是使用shiro的核心。这也是shiro和数据库建立连接的核心,因为这里用户的角色和权限都是调用service层查询数据库得到的信息,因此applicationContxt-shiro.xml和spring.xml配置文件一定要放在一起,都放在contextlistener中加载,不然因为这个realm类先加载,会导致service无法正常注入
public class MyRealm extends AuthorizingRealm{@Autowiredprivate UserService userService;//当这个为null,是因为spring.xml这个文件在applicationContxt-shiro.xml之后加载的,是配置shiro配置文件加载顺序有问题,我直接全放在contextLoaderListener加载配置文件//授权。根据用户名查询用户对应的角色,然后根据角色查询对应的权限,并将角色和权限通过set方法设置给shiro框架。其次授权的前提是一定认证了@Overrideprotected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {User user=(User)principals.getPrimaryPrincipal();//获取用户信息Set<String> roles=userService.selectRolesByUsername(user.getUsername());//根据用户名查询用户对应的角色System.out.println("roles = " + roles);Set<String> permissions=userService.selectPermissionsByRoles(roles);//根据用户角色查询权限System.out.println("permissions = " + permissions);SimpleAuthorizationInfo simpleAuthorizationInfo=new SimpleAuthorizationInfo();simpleAuthorizationInfo.setRoles(roles);//设置角色simpleAuthorizationInfo.setStringPermissions(permissions);//设置权限return simpleAuthorizationInfo;}//注意自定义的realm中执行sql语句对应的方法即使出错也不会报异常//认证。该方法主要用于通过用户输入的账号查询数据库对应的用户信息,传递真实密码。并将查到的用户信息传给上面的授权方法,给用户进行授权@Overrideprotected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {String username = (String)token.getPrincipal();//通过token获取用户输入的账号, token.getCredentials()才是获取密码User user = (User) userService.selectUserByUsername(username);System.out.println("user:"+user);//ByteSource salt=ByteSource.Util.bytes(user.getSalt());//从数据库获取盐。user.getSalt()是用户表盐字段对应的user类的盐的属性。这里没加盐因此没写,这个是下面的第三个参数if (user == null) {//这代表根据账号没查到return null;}else {//这代表根据账号查到了用户信息SimpleAuthenticationInfo authenticationInfo=new SimpleAuthenticationInfo(user,user.getPassword(),"myrealm");//将用户信息传给调用自定义realm的controller类那。第一个参数是用户信息,controller层可通过subject.getpricinple获取,一般显示登录用户名用;第二个是用户密码,这个就是调用这个realm的securityManager底层比对密码的真实密码;第三个应该是盐,告诉shiro我们加密用的盐,但这用不到所以没写。第三个是随便的一个名字return authenticationInfo;}}
}

步骤五:在resouces下创建applicationContxt-shiro.xml配置文件,配置自定义realm、securityManager、拦截哪些地址资源等信息

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"><!-- 该文件需要配realm、 secritymanager即shiro三大组成部分的其中两个,另外一个是subject --><!-- realm --><bean id="myrealm" class="com.qf.realm.MyRealm"><!--告诉shiro过滤器我们自定义的realm在哪--><!-- 此处写密码匹配,使用什么加密--><!--        <property name="credentialsMatcher"><bean class="org.apache.shiro.authc.credential.HashedCredentialsMatcher">&lt;!&ndash; 告诉shiro我们密码加密算法为SHA-256&ndash;&gt;<property name="hashAlgorithmName" value="SHA-256"></property>&lt;!&ndash; 告诉shiro我们密码加密次数 &ndash;&gt;<property name="hashIterations" value="10000"></property>&lt;!&ndash;// 默认的是toString转换成16进制,也就是true。用sha256将值改为false&ndash;&gt;<property name="storedCredentialsHexEncoded" value="false"></property></bean></property>--></bean><!-- 自定义退出登陆 --><bean id="logout" class="org.apache.shiro.web.filter.authc.LogoutFilter"><property name="redirectUrl" value="/userftl/login" /><!--shiro自带的退出登录,此处表示/userftl/login就是触发shiro自带的突出登录的请求地址--></bean><!--创建securityManager对象--><bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager"><property name="realm" ref="myrealm" /></bean><!-- 创建shiro过滤器,用于授权管理。intercepter拦截器是spring所独有的,因此shiro底层授权用的是过滤器--><!-- 授权管理 --><bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean"><property name="securityManager" ref="securityManager" /><!--配置登录页面,认证不通过的会自动跳转到这个页面--><property name="loginUrl" value="/userftl/login" /><!--loginUrl对应的值是shiro自带的登录页面,/userftl/login这个请求地址是我们自己写的,它对应的处理方法就只有跳转登录页面--><!-- 配置被拦截的未授权时跳转的页面--><property name="unauthorizedUrl" value="/userftl/403" /><!--/userftl/403这个请求地址在这个案例中它对应的方法就只写了个跳转去未授权页面的--><!--配置过滤链,这才是shiro拦截的核心,定义请求地址被那种方式访问。anon代表匿名地址即不登录就可以访问的;authc代表公共访问地址,需要授权才能访问--><!--anon定义的是不用登录(认证)就可以访问的请求地址,authc是必须登录(认证)才能放行。anon和authc其实就是两个不同条件的过滤器,本质就是过滤器--><property name="filterChainDefinitions"><!--格式:  请求地址=anon   ,反正左侧就是资源(请求地址、静态资源),右侧就是申明请求地址的类型--><value>/test=anon/userftl/login=anon/user/login=anon/=anon    <!--/代表项目启动后访问的默认页面-->/userftl/403=anon<!-- 静态资源一定要设置为匿名资源-->/css/**=anon/font/**=anon/image/**=anon/js/**=anon/store/**=anon/user/logout=logout
<!--                授权的前提一定是已经认证过了,这是shiro默认的,也就意味着想接触授权的地址,一定是用户已经登录了roles[1,2]同时需要拥有两个角色才可以访问 ! and的关系-->/productftl/add=roles[管理员]  <!--roles[管理员]代表只有被授予管理员角色的才能访问,如果为roles[管理员,普通用户]代表要同时是管理员又是普通用户才能访问的请求地址--><!--请求地址=perms[权限1,权限2]-->/**=authc        <!--/** 代表拦截所有路径,除了上面被定义为匿名地址的请求路径--></value></property></bean></beans>

步骤六:配置WEB-INF下的web.xml文件,加载配置文件以及加载shiro的全局过滤器,只有配置了这个全局过滤器拦截才生效

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://java.sun.com/xml/ns/javaeehttp://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"version="3.0"><!--头部信息换成3.0,不然</async-supported>会报错,--><display-name>Archetype Created Web Application</display-name><!--利用DispatcherServlet核心类加载spring.xml配置文件--><servlet><servlet-name>aa</servlet-name><!--与servlet-mapping中的servlet-name要保持一致--><servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class><init-param><param-name>contextConfigLocation</param-name><param-value></param-value><!--只有DispatcherServlet才能加载spring.xml文件,因为他是子容器,子容器能访问父容器--></init-param></servlet><servlet-mapping><servlet-name>aa</servlet-name><url-pattern>/</url-pattern></servlet-mapping><!--一定要用ContextLoaderListener加载applicationContxt-shiro.xml配置文件,不然会报错--><context-param><param-name>contextConfigLocation</param-name><param-value>classpath:spring.xml,classpath:applicationContxt-shiro.xml</param-value><!--applicationContxt-shiro.xml一定要在ContextLoaderListener中加载,因为这是父容器。父容器先加载--></context-param><listener><listener-class>org.springframework.web.context.ContextLoaderListener</listener-class></listener><!--用于初始化shiro中的所有过滤器--><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><!--/*代表过滤所有请求,只有拦截完了,我们才好在applicationContxt-shiro.xml中去决定放行哪些请求--></filter-mapping><!--处理post乱码,设置字符集--><filter><filter-name>bb</filter-name><!--与下面的filter-mapping中的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>bb</filter-name><url-pattern>/*</url-pattern><!--给所有文件设置字符集--></filter-mapping></web-app>

本次案例ssm+shiro+jsp标签框架就搭配完了,下面就开始案例的书写


步骤七:创建案例要使用的controller层、service层、dao层以及数据库表对应的实体类

数据库表对应的实体类
第一个实体类:User

package com.qf.entity;import java.util.List;public class User {private Integer uid;private String username;private String password;private String nickname;List<Role>  roles;public List<Role> getRoles() {return roles;}public void setRoles(List<Role> roles) {this.roles = roles;}public Integer getUid() {return uid;}public void setUid(Integer uid) {this.uid = uid;}public String getUsername() {return username;}public void setUsername(String username) {this.username = username == null ? null : username.trim();}public String getPassword() {return password;}public void setPassword(String password) {this.password = password == null ? null : password.trim();}public String getNickname() {return nickname;}public void setNickname(String nickname) {this.nickname = nickname == null ? null : nickname.trim();}@Overridepublic String toString() {return "User{" +"uid=" + uid +", username='" + username + '\'' +", password='" + password + '\'' +", nickname='" + nickname + '\'' +", roles=" + roles +'}';}
}

第二个实体类:Role

package com.qf.entity;import java.util.List;public class Role {private Integer rid;private String rname;private String rinfo;private List<Permission> permissions;public List<Permission> getPermissions() {return permissions;}public void setPermissions(List<Permission> permissions) {this.permissions = permissions;}public Integer getRid() {return rid;}public void setRid(Integer rid) {this.rid = rid;}public String getRname() {return rname;}public void setRname(String rname) {this.rname = rname == null ? null : rname.trim();}public String getRinfo() {return rinfo;}public void setRinfo(String rinfo) {this.rinfo = rinfo == null ? null : rinfo.trim();}@Overridepublic String toString() {return "Role{" +"rid=" + rid +", rname='" + rname + '\'' +", rinfo='" + rinfo + '\'' +", permissions=" + permissions +'}';}
}

第三个实体类:Permission

package com.qf.entity;public class Permission {private Integer pid;private String pname;private String paction;private String pinfo;public Integer getPid() {return pid;}public void setPid(Integer pid) {this.pid = pid;}public String getPname() {return pname;}public void setPname(String pname) {this.pname = pname == null ? null : pname.trim();}public String getPaction() {return paction;}public void setPaction(String paction) {this.paction = paction == null ? null : paction.trim();}public String getPinfo() {return pinfo;}public void setPinfo(String pinfo) {this.pinfo = pinfo == null ? null : pinfo.trim();}
}

controller层的类:
本案例controller层的重点类:UserController

package com.qf.controller;import com.qf.entity.User;
import com.qf.service.UserService;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.support.SessionStatus;import javax.annotation.Resource;@RequestMapping("/user")
@Controller
public class UserController {@Resourceprivate UserService userService;@RequestMapping("/login")public String login(User user, ModelMap modelMap){// User封装登录页面表单传过来的用户名和密码String  path="login";//注意这种用变量表示路径的方式UsernamePasswordToken usernamePasswordToken=new UsernamePasswordToken(user.getUsername(),user.getPassword());//user.getUsername()为用户输入的账号,user.getPassword()为用户输入的密码Subject subject = SecurityUtils.getSubject();//获取用户对象try{subject.login(usernamePasswordToken);//shiro底层完成登录验证path="home";User loginUser = (User)subject.getPrincipal();//获取在自定义realm中想传过来的值;jsp页面中的shiro标签获取到的就是认证后的信息modelMap.addAttribute("user",loginUser);return path;}catch (Exception e){User user2 = (User) userService.selectUserByUsername(user.getUsername());modelMap.addAttribute("msg","认证失败");return path;}}@RequestMapping("/logout")public String logout(ModelMap modelMap, SessionStatus sessionStatus){sessionStatus.setComplete();modelMap.addAttribute("msg","退出登录成功");return "login";}
}

第二个controller类:ProductFtlController,用于测试页面用的

package com.qf.controller;import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;@Controller
@RequestMapping("/productftl")
public class ProductFtlController {@RequestMapping("/show")public  String jumpShow(){return  "show";}@RequestMapping("/add")public String humpAdd(){return "show";}
}

第三个controller类:UserFtlController,用于跳转页面的

package com.qf.controller;import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;@Controller
@RequestMapping("/userftl")
public class UserFtlController {@RequestMapping("/403")public String jump403(){System.out.println("UserFtlController.jump403");return "403";}@RequestMapping("/home")public String jumpHome(){System.out.println("UserFtlController.jumpHome");return "home";}@RequestMapping("login")public String jumpLogin(){System.out.println("UserFtlController.jumpLogin");return "login";}
}

service层的接口及其实现类:
service层接口:UserService

package com.qf.service;import com.qf.entity.User;import java.util.List;
import java.util.Map;
import java.util.Set;public interface UserService {
public User selectUserByUsername(String username);public   Set<String> selectRolesByUsername(String username);public Set<String> selectPermissionsByRoles(Set<String> roles);
}

service层UserService对应的实现类:UserServiceImpl

package com.qf.service.impl;import com.qf.dao.UserDao;
import com.qf.entity.User;
import com.qf.service.UserService;
import org.springframework.stereotype.Service;import javax.annotation.Resource;
import java.util.List;
import java.util.Set;@Service
public class UserServiceImpl implements UserService {@Resourceprivate UserDao userDao;@Overridepublic User selectUserByUsername(String username) {User user = userDao.selectUserAndRolesAndPerminssion(username);return user;}@Overridepublic Set<String> selectRolesByUsername(String username) {//根据用户名查询 角色信息Set<String> roles = userDao.selectRolesByUsername(username);return roles;}@Overridepublic Set<String> selectPermissionsByRoles(Set<String> roles) {//根据角色查权限信息Set<String> permissions = userDao.selectPermissionsByRoles(roles);return permissions;}
}

dao层的接口:

package com.qf.dao;import com.qf.entity.User;
import org.springframework.stereotype.Component;import java.util.List;
import java.util.Map;
import java.util.Set;
@Component
public interface UserDao {
public User  selectUserAndRolesAndPerminssion(String username);//根据用户名查询用户Set<String> selectRolesByUsername(String username);//根据用户名查询角色Set<String> selectPermissionsByRoles(Set<String> roles);//根据用户角色查询权限
}

步骤八:在resouces文件夹下创建mapper文件夹,用于写dao层对应的sql语句

在mapper文件夹下创建本次案例dao层对应的sql语句的xml文件:userMapper.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.qf.dao.UserDao"><resultMap id="BaseResultMap" type="com.qf.entity.User"><id column="uid" jdbcType="INTEGER" property="uid" /><result column="username" jdbcType="VARCHAR" property="username" /><result column="PASSWORD" jdbcType="VARCHAR" property="password" /><result column="nickname" jdbcType="VARCHAR" property="nickname" /></resultMap><resultMap id="selectUserAndRolesAndPerminssion" type="com.qf.entity.User"><id column="uid" jdbcType="INTEGER" property="uid" /><result column="username" jdbcType="VARCHAR" property="username" /><result column="PASSWORD" jdbcType="VARCHAR" property="password" /><result column="nickname" jdbcType="VARCHAR" property="nickname" /><collection property="roles" ofType="com.qf.entity.Role"><id column="rid" jdbcType="INTEGER" property="rid" /><result column="rname" jdbcType="VARCHAR" property="rname" /><result column="rinfo" jdbcType="VARCHAR" property="rinfo" /><collection property="permissions" ofType="com.qf.entity.Permission"><id column="pid" jdbcType="INTEGER" property="pid" /><result column="pname" jdbcType="VARCHAR" property="pname" /><result column="paction" jdbcType="VARCHAR" property="paction" /><result column="pinfo" jdbcType="VARCHAR" property="pinfo" /></collection></collection></resultMap><select id="selectUserAndRolesAndPerminssion" resultMap="selectUserAndRolesAndPerminssion">SELECT u.*,r.*,p.* FROM user u JOIN  user_role ur ON u.uid=ur.uidJOIN  role r ON ur.rid=r.ridJOIN role_permission rp on  rp.rid=r.ridJOIN permission p on rp.pid=p.pidWHERE  u.username=#{username}</select><select id="selectUserByUsername" resultMap="selectUserAndRolesAndPerminssion">SELECT u.*,r.*,p.* FROM user u JOIN  user_role ur ON u.uid=ur.uidJOIN  role r ON ur.rid=r.ridJOIN role_permission rp on  rp.rid=r.ridJOIN permission p on rp.pid=p.pidWHERE  u.username=#{username}</select><!--因为返回的结果类型为String类型,因此 resultMap="String"--><select id="selectRolesByUsername" resultType="java.lang.String" >SELECT r.rname from USER u JOIN  user_role ur on u.uid =ur.uidJOIN role r ON ur.rid=r.ridWHERE  u.username=#{username}</select><select id="selectPermissionsByRoles" resultType="java.lang.String" >SELECT p.pname FROM  role r join role_permission rp on r.rid = rp.ridjoin permission p on rp.pid = p.pidwhere  r.rname in<foreach collection="collection" open="("  close=")" separator="," item="rname">#{rname}</foreach></select></mapper>

步骤九:定义本次案例用到的jsp页面

第一个jsp页面: login.jsp

<%@page contentType="text/html; charset=utf-8" language="java" pageEncoding="UTF-8"  %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"/><meta http-equiv="X-UA-Compatible" content="IE=9; IE=8; IE=7; IE=EDGE"/><title>商城展示登陆页面</title><link rel="stylesheet" href="/css/index.css" type="text/css"/><link href="/css/layui.css" rel="stylesheet" type="text/css"/><script src="/js/common/jquery-1.8.3.js" type="text/javascript"></script><script src="/js/layui.js" type="text/javascript"></script><style type="text/css">html,body{height: 100%;width: 100%;}</style></head>
<body><div class="container" style="height: 100%"><center><form class="layui-form" action="/user/login"  method="post" lay-filter="example" style="padding-top: 12%"><div class="layui-form-item"><label class="layui-form-label layui-col-sm-offset4 layui-col-sm1" >账号:</label><div class="layui-input-block  layui-col-sm4" ><input type="text" name="username" lay-verify="title" autocomplete="off" placeholder="请输入账号!" class="layui-input"></div></div><div class="layui-form-item"><label class="layui-form-label layui-col-sm-offset3 layui-col-sm1">密码:</label><div class="layui-input-block layui-col-sm4"><input type="password" name="password" placeholder="请输入密码!" autocomplete="off" class="layui-input"></div></div><div class="layui-form-item"><div class="layui-input-block"><button type="button" class="layui-btn layui-btn-normal" id="LAY-component-form-getval">注册</button><button type="submit" class="layui-btn" lay-submit="" lay-filter="demo1">登陆</button></div></div></form><%--<font color="red" size="5">${msg!"欢迎登陆!"}</font>--%></center>
</div>
</body></html>

第二个jsp页面: home.jsp

<%@ taglib prefix="shiro" uri="http://shiro.apache.org/tags" %>
<%@ taglib prefix="shir" uri="http://shiro.apache.org/tags" %>
<%@page contentType="text/html; charset=utf-8" language="java" pageEncoding="UTF-8"  %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"/><meta http-equiv="X-UA-Compatible" content="IE=9; IE=8; IE=7; IE=EDGE"/><title>登录成功展示页面</title><link rel="stylesheet" href="/css/index.css" type="text/css"/><link href="/css/layui.css" rel="stylesheet" type="text/css"/><script src="/js/common/jquery-1.8.3.js" type="text/javascript"></script><script src="/js/layui.js" type="text/javascript"></script><style type="text/css">html,body{height: 100%;width: 100%;}</style></head>
<body>
<a href="/user/logout">退出登录</a>
<hr>获取账号信息:<br>欢迎:${user.username}登录<br>欢迎:[<shiro:principal />]登录<%--principal获取的是自定义realmr认证方法中SimpleAuthenticationInfo那存的第一个参数的值,前提是认证通过后才能获取到--%>
<hr>
认证标签<br>
<shiro:authenticated><%--只有用户在登录时shiro中的认证方法通过了,来到这个页面才会现实的内容--%>认证通过才会显示
</shiro:authenticated><br>
<shiro:notAuthenticated><%--这标签几乎没用,因为没认证的都会被拦截下来--%>没有认证通过才会显示的内容
</shiro:notAuthenticated><br>
<hr>
<shiro:guest><%----%>游客登录时显示的内容
</shiro:guest>
<hr>
授权标签:<shiro:hasRole name="用户"><button>商品展示</button></shiro:hasRole><shiro:hasRole name="管理员"><button>商品展示</button><button>商品添加</button></shiro:hasRole><shiro:hasAnyRoles name="用户,管理员"><%--通过自定义realm认证后的用户,管理员这两个角色满足其一就可以显示这个标签中的内容--%>用户或者管理员这两个角色满足其一就会显示的内容
</shiro:hasAnyRoles><shiro:hasRole name="用户"><shiro:hasRole name="管理员">and  用户管理员</shiro:hasRole>
</shiro:hasRole><hr>
<shir:lacksRole name="用户"><%--当前登录用户没有用户这个角色才会执行的标签--%>没有用户这个角色时才起作用的标签
</shir:lacksRole><hr>
<hr>
以上是角色相关的shiro标签<br>以下是权限相关的shiro标签
<hr>
<hr>
<shiro:hasPermission name="商品展示"><%--当前登录用户有商品展示权限才会起作用的shiro标签--%>当前登录用户有商品展示的权限才会起作用的shiro标签
</shiro:hasPermission><br><shiro:lacksPermission name="商品添加"><%--当前认证用没有商品添加的权限才会起作用的标签--%>当前登录用户没有商品展示权限才会起作用的shiro标签
</shiro:lacksPermission></body>
<script>var element;layui.use('element', function(){//element操作导航条element = layui.element;});/*点击左侧导航条进行切换!item中data属性包含对应要跳转的路径!添加右侧对应的切换tab!并且添加添加显示内容对应的iframe!添加之前先要进行判断是否存在,tab id使用data属性设置!如果存在tabchange如果不存在!添加!并显示状态class="layui-this"*/function navchick(item) {// 就是路径  tab datavar data =  $(item).attr('data');  //获取的data属性//展示var text =  $(item).text();  //获取文本内容//查看data作为id是否出现 如果出现就切换  没有出现就添加//横着的列表var titleli_list = $(".layui-tab-title li");var exist = false;  //默认不存在titleli_list.each(function(){var temp = $(this).attr("lay-id");if (temp == data) {exist = true;return false;}});console.log(exist)if(exist){//如果存在,切换到对应位置即可//存在 切换//切换//c参数1 : lay-filter//参数2: tab的id}else{var iframe_id = 'i'+data;   //idvar iframe_src = data;//src内容//如果不存在,创建内容内别换显示//创建并切换element.tabAdd('test1',{title:text,id:data,content:"<iframe id='+' src='-' frameborder=\"0\" height=\"100%\" width=\"100%\"></iframe>".replace('+',iframe_id).replace('-',iframe_src)});}element.tabChange("test1",data);}</script>
</html>


案例结构图:

红框圈出来的是本案例的核心要点

本次案例用到的数据库:shiroweb

/*
SQLyog Ultimate v12.09 (64 bit)
MySQL - 5.5.40 : Database - shiroweb
*********************************************************************
*//*!40101 SET NAMES utf8 */;/*!40101 SET SQL_MODE=''*/;/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
CREATE DATABASE /*!32312 IF NOT EXISTS*/`shiroweb` /*!40100 DEFAULT CHARACTER SET utf8 */;USE `shiroweb`;/*Table structure for table `permission` */DROP TABLE IF EXISTS `permission`;CREATE TABLE `permission` (`pid` int(11) NOT NULL AUTO_INCREMENT COMMENT '权限主键',`pname` varchar(20) NOT NULL COMMENT '权限的名称',`paction` varchar(100) NOT NULL COMMENT '权限的路径',`pinfo` varchar(200) DEFAULT NULL COMMENT '权限的描述',PRIMARY KEY (`pid`),UNIQUE KEY `pname` (`pname`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;/*Data for the table `permission` */insert  into `permission`(`pid`,`pname`,`paction`,`pinfo`) values (1,'商品添加','/productftl/add','aaa'),(2,'商品展示','/product/ftl/show','商品展示功能,认证用户随便访问');/*Table structure for table `product` */DROP TABLE IF EXISTS `product`;CREATE TABLE `product` (`pid` varchar(96) DEFAULT NULL,`pname` varchar(150) DEFAULT NULL,`market_price` double DEFAULT NULL,`shop_price` double DEFAULT NULL,`pimage` varchar(600) DEFAULT NULL,`pdate` date DEFAULT NULL,`pdesc` varchar(765) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;/*Data for the table `product` */insert  into `product`(`pid`,`pname`,`market_price`,`shop_price`,`pimage`,`pdate`,`pdesc`) values ('51','小米 4c 标准版',1399,1299,'products/1/c_0001.jpg','2015-11-02','小米 4c 标准版 全网通 白色 移动联通电信4G手机 双卡双待'),('10','华为 Ascend Mate7',2699,2599,'products/1/c_0010.jpg','2015-11-02','华为 Ascend Mate7 月光银 移动4G手机 双卡双待双通6英寸高清大屏,纤薄机身,智能超八核,按压式指纹识别!!选择下方“移动老用户4G飞享合约”,无需换号,还有话费每月返还!'),('51','小米 4c 标准版',1399,1299,'products/1/c_0001.jpg','2015-11-02','小米 4c 标准版 全网通 白色 移动联通电信4G手机 双卡双待'),('17','华为 Ascend Mate7',2699,2599,'products/1/c_0010.jpg','2015-11-02','华为 Ascend Mate7 月光银 移动4G手机 双卡双待双通6英寸高清大屏,纤薄机身,智能超八核,按压式指纹识别!!选择下方“移动老用户4G飞享合约”,无需换号,还有话费每月返还!'),('18','vivo X5Pro',2399,2298,'products/1/c_0014.jpg','2015-11-02','移动联通双4G手机 3G运存版 极光白【购机送蓝牙耳机+蓝牙自拍杆】新升级3G运行内存·双2.5D弧面玻璃·眼球识别技术'),('19','努比亚(nubia)My 布拉格',1899,1799,'products/1/c_0013.jpg','2015-11-02','努比亚(nubia)My 布拉格 银白 移动联通4G手机 双卡双待【嗨11,下单立减100】金属机身,快速充电!布拉格相机全新体验!'),('27','华为 麦芒4',2599,2499,'products/1/c_0012.jpg','2015-11-02','华为 麦芒4 晨曦金 全网通版4G手机 双卡双待金属机身 2.5D弧面屏 指纹解锁 光学防抖'),('28','vivo X5M',1899,1799,'products/1/c_0011.jpg','2015-11-02','vivo X5M 移动4G手机 双卡双待 香槟金【购机送蓝牙耳机+蓝牙自拍杆】5.0英寸大屏显示·八核双卡双待·Hi-Fi移动KTV'),('29','Apple iPhone 6 (A1586)',4399,4288,'products/1/c_0015.jpg','2015-11-02','Apple iPhone 6 (A1586) 16GB 金色 移动联通电信4G手机长期省才是真的省!点击购机送费版,月月送话费,月月享优惠,畅享4G网络,就在联通4G!'),('51','小米 4c 标准版',1399,1299,'products/1/c_0001.jpg','2015-11-02','小米 4c 标准版 全网通 白色 移动联通电信4G手机 双卡双待'),('17','华为 Ascend Mate7',2699,2599,'products/1/c_0010.jpg','2015-11-02','华为 Ascend Mate7 月光银 移动4G手机 双卡双待双通6英寸高清大屏,纤薄机身,智能超八核,按压式指纹识别!!选择下方“移动老用户4G飞享合约”,无需换号,还有话费每月返还!'),('32','vivo X5Pro',2399,2298,'products/1/c_0014.jpg','2015-11-02','移动联通双4G手机 3G运存版 极光白【购机送蓝牙耳机+蓝牙自拍杆】新升级3G运行内存·双2.5D弧面玻璃·眼球识别技术'),('33','努比亚(nubia)My 布拉格',1899,1799,'products/1/c_0013.jpg','2015-11-02','努比亚(nubia)My 布拉格 银白 移动联通4G手机 双卡双待【嗨11,下单立减100】金属机身,快速充电!布拉格相机全新体验!'),('34','华为 麦芒4',2599,2499,'products/1/c_0012.jpg','2015-11-02','华为 麦芒4 晨曦金 全网通版4G手机 双卡双待金属机身 2.5D弧面屏 指纹解锁 光学防抖'),('35','vivo X5M',1899,1799,'products/1/c_0011.jpg','2015-11-02','vivo X5M 移动4G手机 双卡双待 香槟金【购机送蓝牙耳机+蓝牙自拍杆】5.0英寸大屏显示·八核双卡双待·Hi-Fi移动KTV'),('36','Apple iPhone 6 (A1586)',4399,4288,'products/1/c_0015.jpg','2015-11-02','Apple iPhone 6 (A1586) 16GB 金色 移动联通电信4G手机长期省才是真的省!点击购机送费版,月月送话费,月月享优惠,畅享4G网络,就在联通4G!'),('51','小米 4c 标准版',1399,1299,'products/1/c_0001.jpg','2015-11-02','小米 4c 标准版 全网通 白色 移动联通电信4G手机 双卡双待'),('17','华为 Ascend Mate7',2699,2599,'products/1/c_0010.jpg','2015-11-02','华为 Ascend Mate7 月光银 移动4G手机 双卡双待双通6英寸高清大屏,纤薄机身,智能超八核,按压式指纹识别!!选择下方“移动老用户4G飞享合约”,无需换号,还有话费每月返还!'),('45','vivo X5Pro',2399,2298,'products/1/c_0014.jpg','2015-11-02','移动联通双4G手机 3G运存版 极光白【购机送蓝牙耳机+蓝牙自拍杆】新升级3G运行内存·双2.5D弧面玻璃·眼球识别技术'),('40','努比亚(nubia)My 布拉格',1899,1799,'products/1/c_0013.jpg','2015-11-02','努比亚(nubia)My 布拉格 银白 移动联通4G手机 双卡双待【嗨11,下单立减100】金属机身,快速充电!布拉格相机全新体验!'),('41','华为 麦芒4',2599,2499,'products/1/c_0012.jpg','2015-11-02','华为 麦芒4 晨曦金 全网通版4G手机 双卡双待金属机身 2.5D弧面屏 指纹解锁 光学防抖'),('42','vivo X5M',1899,1799,'products/1/c_0011.jpg','2015-11-02','vivo X5M 移动4G手机 双卡双待 香槟金【购机送蓝牙耳机+蓝牙自拍杆】5.0英寸大屏显示·八核双卡双待·Hi-Fi移动KTV'),('43','Apple iPhone 6 (A1586)',8888,4288,'products/1/c_0015.jpg','2015-11-02','Apple iPhone 6 (A1586) 16GB 金色 移动联通电信4G手机长期省才是真的省!点击购机送费版,月月送话费,月月享优惠,畅享4G网络,就在联通4G!'),('51','小米 4c 标准版',1399,1299,'products/1/c_0001.jpg','2015-11-02','小米 4c 标准版 全网通 白色 移动联通电信4G手机 双卡双待'),('17','华为 Ascend Mate7',2699,2599,'products/1/c_0010.jpg','2015-11-02','华为 Ascend Mate7 月光银 移动4G手机 双卡双待双通6英寸高清大屏,纤薄机身,智能超八核,按压式指纹识别!!选择下方“移动老用户4G飞享合约”,无需换号,还有话费每月返还!'),('46','vivo X5Pro',2399,2298,'products/1/c_0014.jpg','2015-11-02','移动联通双4G手机 3G运存版 极光白【购机送蓝牙耳机+蓝牙自拍杆】新升级3G运行内存·双2.5D弧面玻璃·眼球识别技术'),('47','努比亚(nubia)My 布拉格',1899,1799,'products/1/c_0013.jpg','2015-11-02','努比亚(nubia)My 布拉格 银白 移动联通4G手机 双卡双待【嗨11,下单立减100】金属机身,快速充电!布拉格相机全新体验!'),('48','华为 麦芒4',2599,2499,'products/1/c_0012.jpg','2015-11-02','华为 麦芒4 晨曦金 全网通版4G手机 双卡双待金属机身 2.5D弧面屏 指纹解锁 光学防抖'),('49','vivo X5M',1899,1799,'products/1/c_0011.jpg','2015-11-02','vivo X5M 移动4G手机 双卡双待 香槟金【购机送蓝牙耳机+蓝牙自拍杆】5.0英寸大屏显示·八核双卡双待·Hi-Fi移动KTV'),('50','Apple iPhone 6 (A1586)',4399,4288,'products/1/c_0015.jpg','2015-11-02','Apple iPhone 6 (A1586) 16GB 金色 移动联通电信4G手机长期省才是真的省!点击购机送费版,月月送话费,月月享优惠,畅享4G网络,就在联通4G!'),('51','小米 4c 标准版',1399,1299,'products/1/c_0001.jpg','2015-11-02','小米 4c 标准版 全网通 白色 移动联通电信4G手机 双卡双待'),('17','华为 Ascend Mate7',2699,2599,'products/1/c_0010.jpg','2015-11-02','华为 Ascend Mate7 月光银 移动4G手机 双卡双待双通6英寸高清大屏,纤薄机身,智能超八核,按压式指纹识别!!选择下方“移动老用户4G飞享合约”,无需换号,还有话费每月返还!');/*Table structure for table `role` */DROP TABLE IF EXISTS `role`;CREATE TABLE `role` (`rid` int(11) NOT NULL AUTO_INCREMENT COMMENT '角色的主键',`rname` varchar(20) NOT NULL COMMENT '角色名称',`rinfo` varchar(100) DEFAULT NULL COMMENT '角色的描述',PRIMARY KEY (`rid`),UNIQUE KEY `rname` (`rname`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;/*Data for the table `role` */insert  into `role`(`rid`,`rname`,`rinfo`) values (1,'用户','一个管理员'),(2,'管理员','哈哈'),(4,'超级管理员','有所有权限');/*Table structure for table `role_permission` */DROP TABLE IF EXISTS `role_permission`;CREATE TABLE `role_permission` (`rp_id` int(11) NOT NULL AUTO_INCREMENT COMMENT '角色和权限表的主键',`rid` int(11) DEFAULT NULL COMMENT '角色表主键',`pid` int(11) DEFAULT NULL COMMENT '权限表主键',PRIMARY KEY (`rp_id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;/*Data for the table `role_permission` */insert  into `role_permission`(`rp_id`,`rid`,`pid`) values (1,1,2),(2,2,1),(3,2,2);/*Table structure for table `user` */DROP TABLE IF EXISTS `user`;CREATE TABLE `user` (`uid` int(11) NOT NULL AUTO_INCREMENT COMMENT '用户的主键',`username` varchar(30) NOT NULL COMMENT '用户账号',`PASSWORD` varchar(200) NOT NULL COMMENT '用户密码',`nickname` varchar(20) DEFAULT '二狗子' COMMENT '用户昵称',PRIMARY KEY (`uid`),UNIQUE KEY `username` (`username`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;/*Data for the table `user` */insert  into `user`(`uid`,`username`,`PASSWORD`,`nickname`) values (1,'customer','1111','二狗子'),(2,'admin','1111','二狗子');/*Table structure for table `user_role` */DROP TABLE IF EXISTS `user_role`;CREATE TABLE `user_role` (`ur_id` int(11) NOT NULL AUTO_INCREMENT COMMENT '用户和角色的中间表主键',`uid` int(11) DEFAULT NULL COMMENT '用户的id',`rid` int(11) DEFAULT NULL COMMENT '角色的id',PRIMARY KEY (`ur_id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;/*Data for the table `user_role` */insert  into `user_role`(`ur_id`,`uid`,`rid`) values (1,1,1),(2,2,2);/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;

本次案例运行结果:
customer用户登录结果:


admin用户登录结果:

ssm+shiro+jsp标签。关键字:shiro的jsp标签,访问拦截。本次ssm和以前的ssm整合中的依赖包不一样。写根据不同用户出现不同的按钮内容就用这shiro标签来解决。Set集合在sql中相关推荐

  1. dependency报红_解决IDEA中Maven依赖包导入失败报红问题(总结最有效8种解决方案)...

    问题描述: 真的,说来话长,这应该是我花最多时间去解决关于Maven依赖包导入的问题,以前粘贴复制导入,自动下载成功了, 这次怎么搞,怎么让他自动下载都还是红红的一片, 花了大半天,各种尝试,只为搏得 ...

  2. ssm+shiro+freemarker。关键字:ftl。(作为了解即可,主要了解ssm+shiro+jsp标签这篇笔记)

    本案例和ssm+shiro+jsp标签这篇文章几乎没差别,差别主要在于spring.xml文件中controller跳转的前后缀的区别以及使用的页面的不同,这个案例页面是ftl,那个案例是jsp页面, ...

  3. SpringMVC对JSP的支持---Spring的JSP标签库---Spring通用标签库

    1. Spring通用标签库 JSP的标签库 除了JSTL(JSP 标准标签库),Spring提供了两个标签库 用来帮助定义Spring MVC Web的视图.  Spring的 表单绑定 JSP标签 ...

  4. dedecms 漏洞_织梦dedecms文档内容页自动关联tag标签加入内链的方法_dedecms_CMS教程...

    效果: 实现教程 1.后台-系统-核心设置-关键字替换,选择[是] 2.后台-系统-其他选项-关键词替换次数,填[1]或者[0] 1:表示文档内容里有多个关键词,只让1个是内链 0:表示文档内容里有多 ...

  5. Shiro与Springboot整合:配置依赖改造登录方法

    <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://mave ...

  6. 火车头采集翻页内容_火车头采集:内容替换支持[参数],标签

    火车头采集:内容替换支持[参数],标签 1, 内容替换 比如我们想要把标题里面的"网购火车票",换为"网购火车头采集器",我们就可以用采集器的替换功能如下图: ...

  7. js如何写html中的内容,javascript怎样获取某个标签的内容?

    在我们平时的JS编程中,经常要获取标签的内容对其进行操作,有很多细节的东西容易被我们忽略,下面让我们来看一下JavaScript如何获取标签中的内容. HTML结构如下: Title 这有个 第一个p ...

  8. springboot整合shiro和session的详细过程和自定义登录拦截器

    文章目录 1.shiro依赖 2.shiro配置 shiro过滤器配置: 关联自定义的其他管理器 自定义会话工厂: 3.登陆时记录用户信息 4.shiro一些工具类的学习 5.自定义登录拦截器 shi ...

  9. 抓取html指定标签内容,javascript怎样获取某个标签的内容?

    在我们平时的JS编程中,经常要获取标签的内容对其进行操作,有很多细节的东西容易被我们忽略,下面让我们来看一下JavaScript如何获取标签中的内容. HTML结构如下: Title 这有个 第一个p ...

最新文章

  1. Java基础教程,第三讲,运算符 变量定义 数据类型转换
  2. Rest 微服务工程搭建02——微服务消费者订单Module模块 || @RequestBody 的重要作用
  3. 框架 路由地址_Django框架的使用
  4. json yeid_【分享】自动格式化输出JSON的小插件分享给大家
  5. C/C++开发工具大比拼【转】
  6. mysql导入库排除某个表_mysql导入数据排除表-mysql导入数据排除某张表或多张表-吾爱编程网...
  7. 分布式锁概念与实现方案
  8. 无任何网络提供程序接受指定的网络路径解决方法
  9. 统计某个路径下的总文件个数,及总行数(不含空行)
  10. java无经验_应届生没有项目经验怎么面试?(java篇)
  11. BokTalk块说全球首款基于区块链技术的即时通讯系统
  12. 最终结束漂泊的身份-我办理北京人才引进的经历
  13. foxmail客户单发送html活动页面(含链接跳转)邮件(发送 转发)
  14. 我说,执着造就了成功
  15. 网络嵌入算法-Network Embedding-LINE/LANE/M-NMF
  16. xargs -0 是什么意思
  17. java申请暨资格审查表_毕业论文答辩申请暨资格审查表刘金花
  18. Blender赛道建模+Gazebo赛道仿真
  19. [转载]R软件包vegan教程 5.1 函数adonis的使用
  20. 博士论文阅读_仿生群智能优化算法及在点云配准中的应用研究

热门文章

  1. win7打开计算机没盘符,计算机U盘盘符不显示怎么办?Win7系统U盘不显解决办法...
  2. Python3(综合练习 绘出多个颜色不同的同心圆)
  3. 关于标识密码的一点认知
  4. 网络直播多人PK计数器,计数工具下载
  5. 数据结构之线性表的查找
  6. QQ运动数据为0问题解决
  7. eclipse如何配置tomcat?
  8. coc部落冲突脚本辅助工具,小曦coc,PHP随机数生成代码
  9. CSS设置块元素和行内元素
  10. 敢于直面惨淡的人生,敢于正视淋漓的鲜血