Apache Shiro是一个功能强大、灵活的,开源的安全框架。它可以干净利落地处理身份验证、授权、企业会话管理和加密。
Apache Shiro的首要目标是易于使用和理解。安全通常很复杂,甚至让人感到很痛苦,但是Shiro却不是这样子的。一个好的安全框架应该屏蔽复杂性,向外暴露简单、直观的API,来简化开发人员实现应用程序安全所花费的时间和精力。
Shiro能做什么呢?
等等——都集成到一个有凝聚力的易于使用的API。
Shiro 致力在所有应用环境下实现上述功能,小到命令行应用程序,大到企业应用中,而且不需要借助第三方框架、容器、应用服务器等。当然 Shiro 的目的是尽量的融入到这样的应用环境中去,但也可以在它们之外的任何环境下开箱即用。
Authentication(认证), Authorization(授权), Session Management(会话管理), Cryptography(加密)被 Shiro 框架的开发团队称之为应用安全的四大基石。那么就让我们来看看它们吧:
还有其他的功能来支持和加强这些不同应用环境下安全领域的关注点。特别是对以下的功能支持:
在表单输入用户名和(明文)密码,和数据库中的(密文)密码比对,设置好Shiro的加密算法后自动帮我们比对,如果和用户名和密码不正确,重定向到当前页面,并且显示错误信息,登录成功则则跳转到list.jsp
登录成功后,list.jsp里面有user.jsp(有user权限的才能访问),admin.jsp(有admin权限才能访问),如果没有权限,自动跳转到设置好的/unauthorized.jsp没有权限的页面,从而体现授权的功能
数据是静态数据,在UserService里面静态生成的,有user(密码:123456)和admin(密码:123456)两个用户,下图中的字符串是经过MD5加密算法后存到数据库中的数据,比对是从页面获得的(明文)数据经过加密算法和数据的比对
静态数据:admin 123456
user 123456
其中,user用户有user权限,admin用户有admin和user权限
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.imooc</groupId>
<artifactId>Spring-Shiro</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging>
<dependencies>
<!-- shiro核心包 -->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-core</artifactId>
<version>1.2.5</version>
</dependency>
<!-- 添加shiro web支持 -->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-web</artifactId>
<version>1.2.5</version>
</dependency>
<!-- 添加shiro spring支持 -->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.2.5</version>
</dependency>
<!-- 添加Shiro 缓存 -->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-ehcache</artifactId>
<version>1.2.2</version>
</dependency>
<!-- 数据库 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.39</version>
</dependency>
<!-- 数据库连接池 c3p0 -->
<dependency>
<groupId>c3p0</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.1.2</version>
</dependency>
<!-- Spring -->
<!-- 添加spring支持 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>4.3.10.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>4.3.10.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.3.10.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>4.3.10.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>4.3.10.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>4.3.10.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>4.3.10.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>4.3.10.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>4.3.10.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>4.3.10.RELEASE</version>
</dependency>
<!-- Servlet -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.0.1</version>
<scope>provided</scope>
</dependency>
<!-- JSP -->
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.1</version>
<scope>provided</scope>
</dependency>
<!-- 添加jstl支持 -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<!-- 添加log4j日志 -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.21</version>
</dependency>
</dependencies>
</project>
重点是shiroFilter这个bean
还要注意:
/jquery/** = anon (此项目jquery下放的是jquery.js文件,当页面访问是也是一个url,设置为可以匿名访问,否则js文件引入不进来)
<script type="text/javascript" src="jquery/jquery-3.2.1.min.js"></script>
<?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">
<!-- 安全管理器 -->
<!-- 配置 SecurityManager -->
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
<property name="cacheManager" ref="cacheManager" />
<property name="realm" ref="jdbcRealm"></property>
<property name="realms">
<list>
<ref bean="jdbcRealm" />
<!-- <ref bean="secondRealm"/> -->
</list>
</property>
</bean>
<!-- 缓存管理器 使用Ehcache实现 -->
<!-- 配置 CacheManager. (需要加入 ehcache 的 依赖 包及配置文件) -->
<bean id="cacheManager" class="org.apache.shiro.cache.ehcache.EhCacheManager">
<property name="cacheManagerConfigFile" value="classpath:ehcache.xml" />
</bean>
<!-- 配置 Realm,实现加密和授权 -->
<bean id="jdbcRealm" class="com.imooc.realms.ShiroRealm">
<!-- 配置加密算法 -->
<property name="credentialsMatcher">
<bean class="org.apache.shiro.authc.credential.HashedCredentialsMatcher">
<!-- 加密的种类 -->
<property name="hashAlgorithmName" value="MD5"></property>
<!-- 加密的次数 -->
<property name="hashIterations" value="1024"></property>
</bean>
</property>
</bean>
<!-- 配置 LifecycleBeanPostProcessor. 可以自定的来调用配置在 Spring IOC 容器中 shiro bean
的生命周期方法. -->
<bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor" />
<!-- 启用 IOC 容器中使用 shiro 的注解. 但必须在配置了 LifecycleBeanPostProcessor 之后才可以使用. -->
<bean
class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"
depends-on="lifecycleBeanPostProcessor" />
<bean
class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">
<property name="securityManager" ref="securityManager" />
</bean>
<!-- 配置 ShiroFilter. id 必须和 web.xml 文件中配置的 DelegatingFilterProxy 的 <filter-name>
一致. 若不一致, 则会抛出: NoSuchBeanDefinitionException. 因为 Shiro 会来 IOC 容器中查找和 <filter-name>
名字对应的 filter bean. -->
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
<property name="securityManager" ref="securityManager" />
<!-- 没有登录的用户请求需要登录的页面时自动跳转到登录页面,不是必须的属性,不输入地址的话会自动寻找项目web项目的根目录下的”/login.jsp”页面 -->
<property name="loginUrl" value="/login.jsp" />
<!-- 登录成功默认跳转页面,不配置则跳转至”/”。如果登陆前点击的一个需要登录的页面,则在登录自动跳转到那个需要登录的页面。不跳转到此 -->
<property name="successUrl" value="/list.jsp" />
<!-- 没有权限默认跳转的页面 -->
<property name="unauthorizedUrl" value="/unauthorized.jsp" />
<!-- 配置哪些页面需要受保护. 以及访问这些页面需要的权限. 1). anon 可以被匿名访问 2). authc 必须认证(即登录)后才可能访问的页面.
3). logout 登出. 4). roles 角色过滤器 -->
<property name="filterChainDefinitions">
<value>
<!-- action可以匿名访问 -->
/*.action=anon
<!-- 登录界面,可以匿名访问 -->
/login.jsp = anon
<!-- js文件可以匿名访问,重点,容易漏掉 -->
/jquery/** = anon
<!-- 退出登录方法可以匿名访问 -->
/logout = logout
<!-- 授权 -->
<!-- user.jsp只有user权限才能访问,否则跳转到/unauthorized.jsp -->
/user.jsp=roles[user]
<!-- admin.jsp只有admin权限才能访问,否则跳转到/unauthorized.jsp -->
/admin.jsp=roles[admin]
<!-- 剩下的所有都要认证后访问 -->
/** = authc
</value>
</property>
</bean>
</beans>
<?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:tx="http://www.springframework.org/schema/tx"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:task="http://www.springframework.org/schema/task"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
http://www.springframework.org/schema/task
http://www.springframework.org/schema/task/spring-task-4.0.xsd">
<context:component-scan base-package="com.imooc.handlers"></context:component-scan>
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/"></property>
<property name="suffix" value=".jsp"></property>
</bean>
<mvc:annotation-driven></mvc:annotation-driven>
<mvc:default-servlet-handler/>
</beans>
<ehcache>
<!-- Sets the path to the directory where cache .data files are created.
If the path is a Java System Property it is replaced by
its value in the running VM.
The following properties are translated:
user.home - User's home directory
user.dir - User's current working directory
java.io.tmpdir - Default temp file path -->
<diskStore path="java.io.tmpdir"/>
<!-- <cache name="authorizationCache"
eternal="false"
timeToIdleSeconds="3600"
timeToLiveSeconds="0"
overflowToDisk="false"
statistics="true">
</cache>
<cache name="authenticationCache"
eternal="false"
timeToIdleSeconds="3600"
timeToLiveSeconds="0"
overflowToDisk="false"
statistics="true">
</cache>
<cache name="shiro-activeSessionCache"
eternal="false"
timeToIdleSeconds="3600"
timeToLiveSeconds="0"
overflowToDisk="false"
statistics="true">
</cache> -->
<!--Default Cache configuration. These will applied to caches programmatically created through
the CacheManager.
The following attributes are required for defaultCache:
maxInMemory - Sets the maximum number of objects that will be created in memory
eternal - Sets whether elements are eternal. If eternal, timeouts are ignored and the element
is never expired.
timeToIdleSeconds - Sets the time to idle for an element before it expires. Is only used
if the element is not eternal. Idle time is now - last accessed time
timeToLiveSeconds - Sets the time to live for an element before it expires. Is only used
if the element is not eternal. TTL is now - creation time
overflowToDisk - Sets whether elements can overflow to disk when the in-memory cache
has reached the maxInMemory limit.
-->
<defaultCache
maxElementsInMemory="10000"
eternal="false"
timeToIdleSeconds="120"
timeToLiveSeconds="120"
overflowToDisk="true"
/>
<!--Predefined caches. Add your cache configuration settings here.
If you do not have a configuration for your cache a WARNING will be issued when the
CacheManager starts
The following attributes are required for defaultCache:
name - Sets the name of the cache. This is used to identify the cache. It must be unique.
maxInMemory - Sets the maximum number of objects that will be created in memory
eternal - Sets whether elements are eternal. If eternal, timeouts are ignored and the element
is never expired.
timeToIdleSeconds - Sets the time to idle for an element before it expires. Is only used
if the element is not eternal. Idle time is now - last accessed time
timeToLiveSeconds - Sets the time to live for an element before it expires. Is only used
if the element is not eternal. TTL is now - creation time
overflowToDisk - Sets whether elements can overflow to disk when the in-memory cache
has reached the maxInMemory limit.
-->
<!-- Sample cache named sampleCache1
This cache contains a maximum in memory of 10000 elements, and will expire
an element if it is idle for more than 5 minutes and lives for more than
10 minutes.
If there are more than 10000 elements it will overflow to the
disk cache, which in this configuration will go to wherever java.io.tmp is
defined on your system. On a standard Linux system this will be /tmp"
-->
<cache name="sampleCache1"
maxElementsInMemory="10000"
eternal="false"
timeToIdleSeconds="300"
timeToLiveSeconds="600"
overflowToDisk="true"
/>
<!-- Sample cache named sampleCache2
This cache contains 1000 elements. Elements will always be held in memory.
They are not expired. -->
<cache name="sampleCache2"
maxElementsInMemory="1000"
eternal="true"
timeToIdleSeconds="0"
timeToLiveSeconds="0"
overflowToDisk="false"
/> -->
<!-- Place configuration for your caches following -->
</ehcache>
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
id="WebApp_ID" version="2.5">
<!-- Spring -->
<!-- needed for ContextLoaderListener -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>
<!-- Bootstraps the root web application context before servlet initialization -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- SpringMVC -->
<servlet>
<servlet-name>springDispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-servlet.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springDispatcherServlet</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>
<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>
</web-app>
package com.imooc.entity;
/*
* User类,用于登录的类
*/
public class User {
private Integer id;//主键
private String username;//用户名
private String password;//密码
@Override
public String toString() {
return "User [id=" + id + ", username=" + username + ", password=" + password + "]";
}
/**
* @return the id
*/
public Integer getId() {
return id;
}
/**
* @param id
* the id to set
*/
public void setId(Integer id) {
this.id = id;
}
/**
* @return the username
*/
public String getUsername() {
return username;
}
/**
* @param username
* the username to set
*/
public void setUsername(String username) {
this.username = username;
}
/**
* @return the password
*/
public String getPassword() {
return password;
}
/**
* @param password
* the password to set
*/
public void setPassword(String password) {
this.password = password;
}
public User(String username, String password) {
this.username = username;
this.password = password;
}
public User() {
}
}
获得到表单的数据并且封装到UsernamePasswordToken对象,调用subject的login方法
package com.imooc.handlers;
import java.util.Map;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.DisabledAccountException;
import org.apache.shiro.authc.ExcessiveAttemptsException;
import org.apache.shiro.authc.ExpiredCredentialsException;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.LockedAccountException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authz.UnauthorizedException;
import org.apache.shiro.subject.Subject;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class LoginHandler {
/*
* 登录action
*/
@RequestMapping("/login.action")
public String login(String username, String password, Map<String, Object> map) {
System.out.println("LoginHandler login...");
// 获得当前Subject
Subject currentUser = SecurityUtils.getSubject();
// 验证用户是否验证,即是否登录
if (!currentUser.isAuthenticated()) {
String msg = "";
// 把用户名和密码封装为 UsernamePasswordToken 对象
UsernamePasswordToken token = new UsernamePasswordToken(username, password);
// remembermMe记住密码
token.setRememberMe(true);
try {
// 执行登录.
currentUser.login(token);
// 登录成功...
return "redirect:/list.jsp";
} catch (IncorrectCredentialsException e) {
msg = "登录密码错误";
System.out.println("登录密码错误!!!" + e);
} catch (ExcessiveAttemptsException e) {
msg = "登录失败次数过多";
System.out.println("登录失败次数过多!!!" + e);
} catch (LockedAccountException e) {
msg = "帐号已被锁定";
System.out.println("帐号已被锁定!!!" + e);
} catch (DisabledAccountException e) {
msg = "帐号已被禁用";
System.out.println("帐号已被禁用!!!" + e);
} catch (ExpiredCredentialsException e) {
msg = "帐号已过期";
System.out.println("帐号已过期!!!" + e);
} catch (UnknownAccountException e) {
msg = "帐号不存在";
System.out.println("帐号不存在!!!" + e);
} catch (UnauthorizedException e) {
msg = "您没有得到相应的授权!";
System.out.println("您没有得到相应的授权!" + e);
} catch (Exception e) {
System.out.println("出错!!!" + e);
}
map.put("msg", msg);
return "/login";
}
// 登录成功,重定向到list.jsp
return "redirect:/list.jsp";
}
}
doGetAuthenticationInfo用于实现验证,在application.xml中配置了此Realm的加密算法
doGetAuthorizationInfo用于实现授权,此项目中是用户默认用于user权限,如果用户名等于admin,还用于admin权限
package com.imooc.realms;
import java.util.HashSet;
import java.util.Set;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
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.util.ByteSource;
import com.imooc.service.UserService;
/*
* 继承AuthorizingRealm,实现doGetAuthenticationInfo(验证)方法和doGetAuthorizationInfo(授权方法)
*/
public class ShiroRealm extends AuthorizingRealm{
/**
* 方面用于加密
* 参数:AuthenticationToken是从表单穿过来封装好的对象
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
System.out.println("doGetAuthenticationInfo:"+token);
//将AuthenticationToken强转为AuthenticationToken对象
UsernamePasswordToken upToken=(UsernamePasswordToken)token;
//获得从表单传过来的用户名
String username=upToken.getUsername();
//从数据库查看是否存在用户
UserService userService=new UserService();
//如果用户不存在,抛此异常
if(!userService.selectUsername(username)){
throw new UnknownAccountException("无此用户名!");
}
//认证的实体信息,可以是username,也可以是用户的实体类对象,这里用的用户名
Object principal=username;
//从数据库中查询的密码
Object credentials=userService.selectPassword(username);
//颜值加密的颜,可以用用户名
ByteSource credentialsSalt=ByteSource.Util.bytes(username);
//当前realm对象的名称,调用分类的getName()
String realmName=this.getName();
//创建SimpleAuthenticationInfo对象,并且把username和password等信息封装到里面
//用户密码的比对是Shiro帮我们完成的
SimpleAuthenticationInfo info=null;
info=new SimpleAuthenticationInfo(principal, credentials, credentialsSalt, realmName);
return info;
}
//用于授权
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
//从PrincipalCollection中获得用户信息
Object principal=principals.getPrimaryPrincipal();
System.out.println("ShiroRealm AuthorizationInfo:"+principal.toString());
//根据用户名来查询数据库赋予用户权限(查数据库)
Set roles=new HashSet<>();
roles.add("user");
if("admin".equals(principal)){
roles.add("admin");
}
SimpleAuthorizationInfo info=new SimpleAuthorizationInfo(roles);
return info;
//return null;
}
}
package com.imooc.service;
import java.util.ArrayList;
import java.util.List;
import org.springframework.stereotype.Service;
import com.imooc.entity.User;
@Service
public class UserService {
//用户的集合
private List<User> users=new ArrayList<>();
public UserService(){
//从数据库查出来的用户名,密码,这是是静态数据
users.add(new User("admin", "038bdaf98f2037b31f1e75b5b4c9b26e"));
users.add(new User("user", "098d2c478e9c11555ce2823231e02ec1"));
}
//判断是否用户名是否存在
public boolean selectUsername(String username){
for (User user : users) {
if(user.getUsername().equals(username)){
return true;
}
}
return false;
}
//根据用户返回查询的密码
public String selectPassword(String username){
for (User user : users) {
if(user.getUsername().equals(username)){
return user.getPassword();
}
}
return "";
}
}
package com.imooc.test;
import org.apache.shiro.crypto.hash.SimpleHash;
import org.apache.shiro.util.ByteSource;
public class MD5Test {
public static void main(String[] args) {
//加密额类型
String algorithmName="MD5";
//密码
Object source="123456";
//盐值加密的盐(一般用用户名做盐值)
String username="user";
ByteSource credentialsSalt=ByteSource.Util.bytes(username);
//加密的次数
int hashIterations=1024;
//执行加密算法,返回加密结果
Object o=new SimpleHash(algorithmName, source, credentialsSalt, hashIterations);
System.out.println("MD5加密后的密码:"+o);
}
}
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Insert title here</title>
</head>
<body>
<h4>Admin Page</h4>
</body>
</html>
<%@ page language="java" import="java.util.*" pageEncoding="ISO-8859-1"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<base href="<%=basePath%>">
<title>My JSP 'index.jsp' starting page</title>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="This is my page">
<!--
<link rel="stylesheet" type="text/css" href="styles.css">
-->
</head>
<body>
This is my JSP page. <br>
</body>
</html>
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<%@ taglib prefix="shiro" uri="http://shiro.apache.org/tags" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Insert title here</title>
</head>
<body>
<h4>List Page</h4>
<br/>
<a href="user.jsp">user</a>
<br/>
<a href="admin.jsp">admin</a>
<br/>
<a href="logout">Logout</a>
</body>
</html>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<script type="text/javascript" src="jquery/jquery-3.2.1.min.js"></script>
<script type="text/javascript">
$(function(){
var msg = '<%=request.getAttribute("msg")%>';//获得LoginMethod中返回的的信息
if(msg!=null&&msg!="null"&&msg!=""){
alert(msg);
}
});
</script>
<title>Insert title here</title>
</head>
<body>
<h4>Login Page</h4>
${msg}
<br>
<br>
<form action="login.action" method="POST">
username: <input type="text" name="username" /> <br> <br>
password: <input type="password" name="password" /> <br> <br>
<input type="submit" value="Submit" />
</form>
</body>
</html>
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Insert title here</title>
</head>
<body>
<h4>Unauthorized Page</h4>
</body>
</html>
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Insert title here</title>
</head>
<body>
<h4>User Page</h4>
</body>
</html>