一、识别操作系统人的身份
1.目标
识别操作系统的人的身份,控制它的行为
2.思路
3.代码
3.1 创建工具方法执行MD5加密
传进一个字符串,返回一个加密的字符串
/**
* 对明文进行MD5加密
* @param source 传入的明文字符串
*
* */
public static String md5(String source) {
// 1.判断source是否有效
if (source == null || source.length() == 0) {
// 2.如果不是有效字符串,抛出异常
throw new RuntimeException(CrowdConstant.MESSAGE_STRING_INVALIDATE);
}
try {
// 3.获取MessageDigest
//algorithm:翻译算法
String algorithm = "md5";
MessageDigest messageDigest = MessageDigest.getInstance(algorithm);
// 4.获取明文字符串的字节数组
byte[] inputs = source.getBytes();
// 5.执行加密
byte[] output = messageDigest.digest(inputs);
// 6.创建bigInteger对象
int signum = 1;
BigInteger bigInteger = new BigInteger(signum, output);
// 7.将bigInteger转为16进制字符串
int radix = 16;
String encode = bigInteger.toString(radix).toUpperCase();
return encode;
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
return null;
}
3.2创建自定义的登录失败异常
/**
* @author hejinjie
* 创建登录失败的异常处理类
* */
public class LoginFailedException extends RuntimeException{
public static final long serialVersionUID = 1L;
public LoginFailedException() {
super();
}
public LoginFailedException(String message) {
super(message);
}
public LoginFailedException(String message, Throwable cause) {
super(message, cause);
}
public LoginFailedException(Throwable cause) {
super(cause);
}
protected LoginFailedException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
super(message, cause, enableSuppression, writableStackTrace);
}
}
3.3 在异常处理器类中增加登录失败异常的处理
/**
* 表示捕获到登录异常类型的异常对象由当前方法处理
* */
@ExceptionHandler(value = LoginFailedException.class)
public ModelAndView resolveLoginFailedException(
LoginFailedException exception,
HttpServletRequest request,
HttpServletResponse response
) throws IOException {
// 只是指定当前异常对应的页面即可
String viewName = "admin-login";
return commonResolveException(viewName, exception, request, response);
}
3.4 在登录页面显示异常消息
3.5 Controller方法
/**
* 登录功能
* @param LoginAcct:前端传来的用户名
* @param userPswd:前端传来的密码
* */
@RequestMapping("/admin/do/login.html")
public String doLogin(@RequestParam String LoginAcct,
@RequestParam String userPswd,
HttpSession session){
System.out.println("LoginAcct="+LoginAcct);
//调用service执行登录检查
//如果能够返回admin说明登录成功,否则登录失败抛出异常
Admin admin = adminService.getAdminByLoginAcct(LoginAcct,userPswd);
System.out.println("admin="+admin);
// 登录成功后将admin对象放入session作用域中
session.setAttribute(CrowdConstant.ATTR_NAME_LOGIN_ADMIN,admin);
// 避免跳转到后台主页面再刷新浏览器导致重复提交表单,重定向到目标页面
return "redirect:/admin/do/main.html";
}
3.6 Service方法
用的是QBZ查询
/**
* 用户登录验证方法
* */
@Override
public Admin getAdminByLoginAcct(String loginAcct, String userPswd) {
System.out.println("表单传入loginAcct="+loginAcct+",密码="+userPswd);
// 1.创建AdminExample对象
AdminExample adminExample = new AdminExample();
// 2.创建Criteria对象
Criteria criteria = adminExample.createCriteria();
// 3.再Criteria对象中封装查询条件
criteria.andLoginAcctEqualTo(loginAcct);
// 4.调用AdminMapper的方法执行查询
List<Admin> list = mapper.selectByExample(adminExample);
// 5.判断Admin对象是否为NULL
if (list==null||list.size()==0){
throw new LoginFailedException(CrowdConstant.MESSAGE_LOGIN_FAILED);
}
Admin admin = list.get(0);
System.out.println("list.get(0)="+admin);
// 6.如果为Null则抛出异常
// 7.如果不为null则将数据库密码从Admin对象中取出
String adminUserPswd = admin.getUserPswd();
System.out.println("数据库的tom密码="+adminUserPswd);
// 8.将表单提交的明文密码进行加密
String md5 = CrowdUtil.md5(userPswd);
// 9.对密码进行比较
if (!(Objects.equals(md5,adminUserPswd))){
throw new LoginFailedException(CrowdConstant.MESSAGE_LOGIN_FAILED);
}
//如果一致返回admin
return admin;
}
3.7 测试
3.8 抽取后台主页面公共部分
目的:省去了大量重复代码
创建JSP模板
二、拦截器:登录状态检查
1.目标
将部分资源保护起来,让没有登录的请求不能访问
2.思路
拦截器的使用:
- 1.创建拦截器类
- 2.注册拦截器类
- 3.完善配套的异常映射
3.代码
3.1创建自定义异常
/**
* @author hejinjie
* 表示用户还没有登录就访问受保护资源异常
* */
public class AccessForbiddenException extends RuntimeException{
private static final long serialVersionUID = 2L;
public AccessForbiddenException() {
super();
}
public AccessForbiddenException(String message) {
super(message);
}
public AccessForbiddenException(String message, Throwable cause) {
super(message, cause);
}
public AccessForbiddenException(Throwable cause) {
super(cause);
}
protected AccessForbiddenException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
super(message, cause, enableSuppression, writableStackTrace);
}
}
3.2创建拦截器类
public class LoginInterceptor extends HandlerInterceptorAdapter {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
// 1.获取session对象
HttpSession session = request.getSession();
// 2.尝试获取Admin对象
Admin admin = (Admin) session.getAttribute(CrowdConstant.ATTR_NAME_LOGIN_ADMIN);
// 3.判断admin是否为空
if (admin==null){
// 4.抛出异常
throw new RuntimeException(CrowdConstant.MESSAGE_LOGIN_FORBIDDEN);
}
// 5.否则说明Admin对象不为null,放行
return true;
}
}
3.3注册拦截器类
<!-- 4.注册拦截器-->
<mvc:interceptors>
<mvc:interceptor>
<!-- mvc:mapping 配置要拦截的资源-->
<!--/*对应一层路径,如/aaa-->
<!--/**对应多层路径,如/aaa/bbb或者/aaa/bbb/ccc或/aaa/bbb/ccc/ddd-->
<mvc:mapping path="/**"/>
<!-- mvc:exclude-mapping 配置不拦截的资源-->
<mvc:exclude-mapping path="/admin/do/login/page.html"/>
<mvc:exclude-mapping path="/admin/do/login.html"/>
<mvc:exclude-mapping path="/admin/do/logout.html"/>
<!--配置拦截器的类-->
<bean class="com.hejinjie.crowd.mvc.interceptor.LoginInterceptor"/>
</mvc:interceptor>
</mvc:interceptors>
3.4完善配套的异常映射
3.4.1基于XML的异常映射