shiro标签只能在jsp和ftl页面文件中使用,无法在html文件中使用
shiro认证后的在jsp页面中的标签:
使用shiro标签就一定要搭配shiro框架使用,即一定要有自定义realm,因为shiro标签的内容就是自定义realm中认证的信息,以及授予的权利
<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>
<?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>
<!–<typeAlias type="com.entity.Student" alias="abc"></typeAlias>–>
<package name="com.qf.entity"></package>
</typeAliases>-->
<!-- <!–展示出mapper文件中执行的sql语句的详细情况–>
<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>
<?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/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/tx
http://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><!–将上面创建好的sqlsesion对象当成SqlSessionTemplate类的一个构造参数–>
</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">
<!– 模板放置的位置 / classpath resources–>
<property name="templateLoaderPath" value="/" /><!–"/"表示ftl模板文件必须放在webapp下。ftl模板放在WEB-INF下的ftl文件夹下时value=/WEB-INF/ftl/,这表示ftl模板文件的位置–>
<property name="defaultEncoding" value="UTF-8" />
</bean>
<!– 页面访问。访问ftl模板文件时,他会自动编译成html文件–>
<bean class="org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver"><!–使用了freemarker视图解析器则必须把InternalResourceViewResolver这个springmvc的视图解析器去掉–>
<property name="contentType" value="text/html;charset=utf-8"/>
<property name="prefix" value="/" /><!–前缀,此时省略也没事–>
<property name="suffix" value=".ftl" /><!–controller层跳转的后缀,当index.ftl模板文件放在webapp下时访问路径:http://localhost:8080/index.ftl–>
</bean>-->
</beans>
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{
@Autowired
private UserService userService;//当这个为null,是因为spring.xml这个文件在applicationContxt-shiro.xml之后加载的,是配置shiro配置文件加载顺序有问题,我直接全放在contextLoaderListener加载配置文件
//授权。根据用户名查询用户对应的角色,然后根据角色查询对应的权限,并将角色和权限通过set方法设置给shiro框架。其次授权的前提是一定认证了
@Override
protected 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语句对应的方法即使出错也不会报异常
//认证。该方法主要用于通过用户输入的账号查询数据库对应的用户信息,传递真实密码。并将查到的用户信息传给上面的授权方法,给用户进行授权
@Override
protected 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;
}
}
}
<?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">
<!– 告诉shiro我们密码加密算法为SHA-256–>
<property name="hashAlgorithmName" value="SHA-256"></property>
<!– 告诉shiro我们密码加密次数 –>
<property name="hashIterations" value="10000"></property>
<!–// 默认的是toString转换成16进制,也就是true。用sha256将值改为false–>
<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
/productftl/add=roles[管理员]
/**=authc
<?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/javaee
http://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>/*
bb
org.springframework.web.filter.CharacterEncodingFilter
encoding
utf-8
bb
/*
数据库表对应的实体类
第一个实体类: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();
}
@Override
public 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();
}
@Override
public 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 {
@Resource
private 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 {
@Resource
private UserDao userDao;
@Override
public User selectUserByUsername(String username) {
User user = userDao.selectUserAndRolesAndPerminssion(username);
return user;
}
@Override
public Set<String> selectRolesByUsername(String username) {
//根据用户名查询 角色信息
Set<String> roles = userDao.selectRolesByUsername(username);
return roles;
}
@Override
public 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);//根据用户角色查询权限
}
在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.uid
JOIN role r ON ur.rid=r.rid
JOIN role_permission rp on rp.rid=r.rid
JOIN permission p on rp.pid=p.pid
WHERE u.username=#{
username}
</select>
<select id="selectUserByUsername" resultMap="selectUserAndRolesAndPerminssion">
SELECT u.*,r.*,p.* FROM user u JOIN user_role ur ON u.uid=ur.uid
JOIN role r ON ur.rid=r.rid
JOIN role_permission rp on rp.rid=r.rid
JOIN permission p on rp.pid=p.pid
WHERE 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.uid
JOIN role r ON ur.rid=r.rid
WHERE 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.rid
join permission p on rp.pid = p.pid
where r.rname in
<foreach collection="collection" open="(" close=")" separator="," item="rname">
#{
rname}
</foreach>
</select>
</mapper>
第一个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 data
var 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; //id
var iframe_src = data;//src内容
//如果不存在,创建内容内别换显示
//创建并切换
element.tabAdd('test1',{
title:text,
id:data,
content:"".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用户登录结果: