什么是shiro
Apache Shiro是一个强大且易用的Java开源安全框架,拥有登录认证、授权管理、企业级会话管理和加密等功能。相比 spring Security 来说要更加的简单。
主要三个核心组件:Subject,SecurityManager 和 Realms
Subject:即“当前操作用户”。但是,在Shiro中,Subject这一概念并不仅仅指人,也可以是第三方进程、后台帐户(Daemon Account)或其他类似事物。它仅仅意味着“当前跟软件交互的东西”。
SecurityManager:它是Shiro框架的核心,典型的Facade模式,Shiro通过SecurityManager来管理内部组件实例,并通过它来提供安全管理的各种服务。
Subject代表了当前用户的安全操作,SecurityManager则管理所有用户的安全操作。
Realm: Realm充当了Shiro与应用安全数据间的“桥梁”或者“连接器”。也就是说,当对用户执行认证(登录)和授权(访问控制)验证时,Shiro会从应用配置的Realm中查找用户及其权限信息。
从这个意义上讲,Realm实质上是一个安全相关的DAO:它封装了数据源的连接细节,并在需要时将相关数据提供给Shiro。当配置Shiro时,你必须至少指定一个Realm,用于认证和(或)授权。配置多个Realm是可以的,但是至少需要一个。
Shiro内置了可以连接大量安全数据源(又名目录)的Realm,如LDAP、关系数据库(JDBC)、类似INI的文本配置资源以及属性文件等。如果缺省的Realm不能满足需求,你还可以插入代表自定义数据源的自己的Realm实现。
pom.xml文件
<properties>
<!-- Spring版本号 -->
<spring.version>5.1.5.RELEASE</spring.version>
<!-- json包jackson-annotations版本号 -->
<jackson.version>2.9.8</jackson.version>
<!-- shiro版本号 -->
<shiro.version>1.3.2</shiro.version>
</properties>
<dependencies>
<!-- slf4j-nop -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-nop</artifactId>
<version>1.7.2</version>
</dependency>
<!-- junit -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<!-- spring core 核心 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency>
<!--spring bean bean的管理 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>${spring.version}</version>
</dependency>
<!--spring context -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<!--spring context support -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- spring web -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- spring mvc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- spring tx -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- spring jdbc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- spring El表达式 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-expression</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- spring test -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- mybatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.6</version>
</dependency>
<!-- mybatis-spring -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>1.3.2</version>
</dependency>
<!-- mysql-connector-java -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
<!-- log4j -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<!-- json包jackson-databind -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>${jackson.version}</version>
</dependency>
<!-- json包jackson-core -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>${jackson.version}</version>
</dependency>
<!-- json包jackson-annotations -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>${jackson.version}</version>
</dependency>
<!-- jstl -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</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-spring</artifactId>
<version>${shiro.version}</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-ehcache</artifactId>
<version>${shiro.version}</version>
</dependency>
<!-- shiro的依赖结束 -->
</dependencies>
jdbc.properties配置文件
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/db_shiro
jdbc.username=root
jdbc.password=root
spring-context.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.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.3.xsd">
<!-- 开启注解扫描,对包中的所有类进行扫描,以完成Bean创建和自动依赖注入的功能 -->
<context:component-scan base-package="com.shiro" />
<!-- 开启注解驱动,启动基于Spring MVC的注解功能,将控制器与方法映射加入到容器中 -->
<mvc:annotation-driven />
<!-- 配置Spring MVC视图解析器 -->
<bean id="ViewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/" />
<property name="suffix" value=".jsp" />
</bean>
</beans>
spring-mybatis.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:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.3.xsd">
<!-- 读取数据库连接的配置文件 -->
<context:property-placeholder
location="classpath:jdbc.properties" />
<!-- 开启注解扫描,并开启注解驱动,用于测试 -->
<!-- <context:component-scan base-package="com.shiro" />
<context:annotation-config /> -->
<!-- 创建数据源,连接数据库 -->
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="${jdbc.driver}" />
<property name="url" value="${jdbc.url}" />
<property name="username" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
</bean>
<!-- 创建sqlSessionFactory工厂,在工厂中依赖数据源,将数据源映射到sqlSessionFactory中 -->
<bean id="sqlSessionFactory"
class="org.mybatis.spring.SqlSessionFactoryBean">
<!-- 配置别名,不用在mybatis-config.xml配置文件中配置别名 -->
<property name="typeAliasesPackage" value="com.shiro.entity" />
<!-- ref中的dataSource是<bean id="dataSource">创建数据源,连接数据库的id值 -->
<property name="dataSource" ref="dataSource" />
<!-- 获得所有的mapper文件,自动扫描mapping.xml文件 -->
<property name="mapperLocations" value="classpath:mappers/*.xml" />
</bean>
<!-- 配置dao接口所在的包。DAO接口所在包名,Spring会自动查找其下的类 -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<!-- 得到所有的dao接口文件,与mapper文件进行对应的映射 -->
<property name="basePackage" value="com.shiro.dao" />
<!-- 依赖sqlSessionFactory工厂 -->
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory" />
</bean>
<!-- 事务管理器(由Spring管理MyBatis的事务) -->
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<!-- 关联数据源 -->
<property name="dataSource" ref="dataSource" />
</bean>
</beans>
spring-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"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- 項目自定义的Realm,从数据库中获取用户的安全数据 -->
<bean id="myShiroRealm" class="com.shiro.utils.MyRealm" />
<!-- 用户授权信息Cache(缓存) -->
<bean id="cacheManager"
class="org.apache.shiro.cache.MemoryConstrainedCacheManager" />
<!-- 配置安全管理器securityManager, 缓存技术: 缓存管理 realm:负责获取处理数据 -->
<bean id="securityManager"
class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
<property name="realm" ref="myShiroRealm" />
<property name="cacheManager" ref="cacheManager" />
</bean>
<!-- shiro的核心配置(自定义权限校验): 配置shiroFileter id名必须与web.xml中的filtername保持一致 -->
<bean id="shiroFilter"
class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
<!-- Shiro的核心安全接口,这个属性是必须的 -->
<property name="securityManager" ref="securityManager" />
<!-- 身份认证失败,跳转到登录页面的配置 -->
<property name="loginUrl" value="/user/login" />
<!-- Shiro的核心安全接口,这个属性是必须的 -->
<property name="successUrl" value="/user/list" />
<!-- 权限认证失败,跳转到指定页面 -->
<property name="unauthorizedUrl" value="/unauthorized.jsp" />
<!-- Shiro连接约束配置,即过滤链的定义 -->
<property name="filterChainDefinitions">
<value>
<!--anon 表示匿名访问,不需要认证以及授权 -->
/user/login = anon
/user/dologin = anon
/user/list = authc
<!-- /api/** = anon -->
<!-- 表示访问/admin请求的用户必须是admin角色,不然是不能进行访问的 -->
<!-- /admin/** = roles[admin] -->
<!-- 表示访问/teacher请求是需要当前用户具有user:create权限才能进行访问的 -->
<!-- /teacher=perms["user:create"] -->
/user/loginOut=logout <!-- 退出登录 -->
<!--authc表示需要认证 没有进行身份认证是不能进行访问的,必须放在最后 -->
/** = authc
</value>
</property>
</bean>
<!-- 必须配置lifecycleBeanPostProcessor为了管理shiro中常见的对象 -->
<!-- 保证实现了Shiro内部lifecycle函数的bean执行 -->
<bean id="lifecycleBeanPostProcessor"
class="org.apache.shiro.spring.LifecycleBeanPostProcessor" />
<!-- 开启Shiro注解 -->
<bean
class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"
depends-on="lifecycleBeanPostProcessor" />
</beans>
web.xml配置文件
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
id="WebApp_ID" version="3.1">
<!-- 可以用 contextloaderlistener + Alt + / 自动生成<context-param>和<listener> -->
<!-- 配置上下文路径参数 -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-*.xml</param-value>
</context-param>
<!-- 配置上下文监听器 -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- 可以用 dispatcherservlet + Alt + / 自动生成<servlet>和<servlet-mapping> -->
<servlet>
<servlet-name>shiro</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!-- 设置spring-context.xml的路径 -->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-context.xml</param-value>
</init-param>
<!-- 1表示启动项目就加载这个类 -->
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>shiro</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<!-- shiro过滤器定义 -->
<filter>
<filter-name>shiroFilter</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
<init-param>
<!-- 该值缺省为false,表示生命周期由SpringApplicationContext管理,设置为true则表示由ServletContainer管理 -->
<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>
<!-- 设置字符编码格式过滤器 -->
<filter>
<filter-name>characterEncodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<!-- 设置编码格式为UTF-8 -->
<param-value>UTF-8</param-value>
</init-param>
<init-param>
<!-- 强制修改字符编码 -->
<param-name>forceRequestEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<!-- 所有请求都要经过该过滤器 -->
<filter-mapping>
<filter-name>characterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
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">
<!-- namespace用接口的全路径作为命名空间 -->
<mapper namespace="com.shiro.dao.UserDao">
<!-- 查询用户全部信息 -->
<select id="list" resultType="User">
select * from t_user
</select>
<!-- 根据用户名来查询用户信息 -->
<select id="findUserByUsername" parameterType="java.lang.String" resultType="User">
select * from t_user where username=#{username}
</select>
<!-- 根据用户名来查询角色信息 -->
<select id="findRoles" parameterType="java.lang.String" resultType="java.lang.String">
select r.role_name from
t_user u,t_role r,t_user_role ur
where u.id = ur.userid
and r.role_id = ur.roleid
and u.username = #{username}
</select>
<!-- 根据用户名来查询权限信息 -->
<select id="findPermissions" parameterType="java.lang.String" resultType="java.lang.String">
select p.permission_name from
t_user u,t_role r,t_permission p,t_user_role ur,t_role_permission rp
where u.id = ur.userid
and r.role_id = ur.roleid
and r.role_id = rp.roleid
and rp.permissionid = p.permission_id
and u.username = #{username}
</select>
</mapper>
Md5Util加密工具类
package com.shiro.utils;
import org.apache.shiro.crypto.hash.Md5Hash;
public class Md5Util {
// 基于shiro的MD5加密,加密结果为32位小写
public static String md5(String str) {
return new Md5Hash(str).toString();
}
}
MyRealm工具类
package com.shiro.utils;
import java.util.Set;
import javax.annotation.Resource;
import org.apache.shiro.SecurityUtils;
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.apache.shiro.subject.SimplePrincipalCollection;
import org.apache.shiro.util.ByteSource;
import com.shiro.entity.User;
import com.shiro.service.UserService;
public class MyRealm extends AuthorizingRealm {
@Resource
private UserService userService;
// 用户授权
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
String username = principals.getPrimaryPrincipal().toString();
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
Set<String> roleName = userService.findRoles(username);
Set<String> permissions = userService.findPermissions(username);
info.setRoles(roleName);
info.setStringPermissions(permissions);
return info;
}
// 登录认证
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
// 获取用户账号
String username = token.getPrincipal().toString();
User user = userService.findUserByUsername(username);
if (user != null) {
// 如果查询到了,封装查询结果
Object principal = user.getUsername();
Object credentials = user.getPassword();
String realmName = this.getName();
String salt = user.getUsername();
ByteSource byteSalt = ByteSource.Util.bytes(salt);// 根据用户名加盐
AuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(principal, credentials, byteSalt,
realmName);
return authenticationInfo;
} else {
return null;
}
}
// 清空当前用户权限信息
public void clearCachedAuthorizationInfo() {
PrincipalCollection principalCollection = SecurityUtils.getSubject().getPrincipals();
SimplePrincipalCollection principals = new SimplePrincipalCollection(principalCollection, getName());
super.clearCachedAuthorizationInfo(principals);
}
// 指定清除principalCollection
public void clearCachedAuthorizationInfo(PrincipalCollection principalCollection) {
SimplePrincipalCollection principals = new SimplePrincipalCollection(principalCollection, getName());
super.clearCachedAuthorizationInfo(principals);
}
}
User实体
package com.shiro.entity;
public class User {
private int id;
private String username;
private String password;
private String phone;
private String nickname;
private String email;
public User() {
super();
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
public String getNickname() {
return nickname;
}
public void setNickname(String nickname) {
this.nickname = nickname;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
@Override
public String toString() {
return "User [id=" + id + ", username=" + username + ", password=" + password + ", phone=" + phone
+ ", nickname=" + nickname + ", email=" + email + "]";
}
}
UserDao层
package com.shiro.dao;
import java.util.List;
import java.util.Set;
import org.springframework.stereotype.Repository;
import com.shiro.entity.User;
@Repository
public interface UserDao {
// 查询用户全部信息
List<User> list();
// 根据用户名来查询用户信息
User findUserByUsername(String username);
// 根据用户名来查询角色信息
Set<String> findRoles(String username);
// 根据用户名来查询权限信息
Set<String> findPermissions(String username);
}
UserService接口
package com.shiro.service;
import java.util.List;
import java.util.Set;
import com.shiro.entity.User;
public interface UserService {
// 查询用户全部信息
List<User> list();
// 根据用户名来查询用户信息
User findUserByUsername(String username);
// 根据用户名来查询角色信息
Set<String> findRoles(String username);
// 根据用户名来查询权限信息
Set<String> findPermissions(String username);
}
UserServiceImpl实现类
package com.shiro.service.impl;
import java.util.List;
import java.util.Set;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.shiro.dao.UserDao;
import com.shiro.entity.User;
import com.shiro.service.UserService;
@Service("userService")
public class UserServiceImpl implements UserService {
@Autowired
private UserDao userDao;
@Override
public List<User> list() {
return userDao.list();
}
@Override
public User findUserByUsername(String username) {
return userDao.findUserByUsername(username);
}
@Override
public Set<String> findRoles(String username) {
return userDao.findRoles(username);
}
@Override
public Set<String> findPermissions(String username) {
return userDao.findPermissions(username);
}
}
UserController层
package com.shiro.controller;
import java.util.List;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.DisabledAccountException;
import org.apache.shiro.authc.ExcessiveAttemptsException;
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.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import com.shiro.entity.User;
import com.shiro.service.UserService;
import com.shiro.utils.Md5Util;
@Controller
@RequestMapping("user")
public class UserController {
@Autowired
private UserService userService;
@GetMapping("login")
public String login() {
return "login";
}
@PostMapping("dologin")
@ResponseBody
public boolean dologin(User user, boolean rememberMe) {
boolean loginflag = false;
// 创建Subject实例对象
Subject currentUser = SecurityUtils.getSubject();
// 判断当前用户是否已登录
if (!currentUser.isAuthenticated()) {
UsernamePasswordToken token = new UsernamePasswordToken(user.getUsername(),
Md5Util.md5(user.getPassword()));
System.out.println(token);
boolean flag = false;
try {
token.setRememberMe(rememberMe);
currentUser.login(token);
loginflag = true;
} catch (DisabledAccountException dax) {
System.out.println("用户名为:" + dax.getMessage() + " 用户已经被禁用!");
flag = true;
} catch (ExcessiveAttemptsException eae) {
System.out.println("用户名为:" + eae + " 用户登录次数过多,有暴力破解的嫌疑!");
flag = true;
} catch (AuthenticationException ae) {
System.out.println("------------------身份认证失败-------------------");
flag = true;
} catch (Exception e) {
System.out.println("未知异常信息。。。。");
flag = true;
}
if (flag) {
return loginflag;
}
}
return loginflag;
}
@GetMapping("list")
public String list(Model model) {
List<User> users = userService.list();
model.addAttribute("users", users);
return "user/list";
}
@GetMapping("loginOut")
public String loginOut() {
return "redirect:/user/login";
}
}
login.jsp页面
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ page import="java.util.Date" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<% pageContext.setAttribute("date", new Date()); %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>登录页面</title>
<link rel="stylesheet" type="text/css" href="https://www.layuicdn.com/layui-v2.5.3/css/layui.css" />
<script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"></script>
<script src="https://www.layuicdn.com/layer-v3.1.0/layer.js"></script>
</head>
<body>
<div class="layui-row layui-col-space5">
<div class="layui-col-md4">
<div class="grid-demo grid-demo-bg1"></div>
</div>
<div class="layui-col-md4">
<div class="grid-demo">
<fieldset class="layui-elem-field layui-field-title"
style="margin-top: 50px;">
<legend>用户登录</legend>
<span style="padding-left: 30px;color: pink;">
<fmt:formatDate value="${date }" pattern="yyyy年MM月dd日"/>
</span>
</fieldset>
<form>
<span id="msg" style="margin-left: 18%; color: red"></span>
<div style="margin-left: -20px;">
<div class="layui-form-item">
<label class="layui-form-label">用户名:</label>
<div class="layui-input-block">
<input type="text" name="username" id="username" lay-verify="title" autocomplete="off" class="layui-input">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">密 码:</label>
<div class="layui-input-block">
<input type="password" name="password" id="password" lay-verify="title" autocomplete="off" class="layui-input">
</div>
</div>
<div class="layui-form-item">
<div class="layui-input-block">
<button type="button" id="login"
class="layui-btn layui-btn-lg layui-btn-primary layui-btn-radius">立即登录</button>
<button style="float: right" type="button" id="register"
class="layui-btn layui-btn-lg layui-btn-primary layui-btn-radius">没有账号?</button>
</div>
</div>
</div>
</form>
</div>
</div>
<div class="layui-col-md4">
<div class="grid-demo grid-demo-bg1"></div>
</div>
</div>
<script type="text/javascript">
$(function() {
$("#login").on("click", function() {
var username = $("#username").val();
var password = $("#password").val();
if(!username) {
$("#msg").html("用户名不能为空!");
$("#username").focus();
return false;
} else {
if(!password) {
$("#msg").html("密码不能为空!");
$("#password").focus();
return false;
} else {
$("#msg").html("");
}
}
$.ajax({
type: "post", // post或get
url: "${pageContext.request.contextPath}/user/dologin", // 提交路径
data: {
username: username,
password: password
},
success: function(data) {
console.log(data);
if (data == true) {
layer.msg('登录中', {
icon: 16
,shade: 0.01
});
// 延迟跳转
window.setTimeout("window.location='${pageContext.request.contextPath}/user/list'",1000);
} else {
layer.tips('用户名或密码错误!', '#login', {
tips: [2, '#3595CC'],
time: 2000
});
}
},
error: function(err) {
layer.msg('数据异常!');
}
})
});
$("#register").on("click", function() {
layer.msg('数据异常!');
});
})
</script>
<!-- <script>
// 防止点击页面后退
history.pushState(null, null, document.URL);
window.addEventListener('popstate', function() {
history.pushState(null, null, document.URL);
});
</script> -->
</body>
</html>
user的list.jsp页面
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="shiro" uri="http://shiro.apache.org/tags" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>用户列表</title>
</head>
<body>
欢迎[ <shiro:principal/> ]登录用户列表
<a href="${pageContext.request.contextPath}/user/loginOut">退出</a>
<hr>
<c:forEach items="${users}" var="user">
${user.id} ----> ${user.username} ----> ${user.phone} ----> ${user.email}<br>
</c:forEach>
</body>
</html>