1:环境:idea 14版本,win10,springboot
2:第一个问题:必须使用shiro实现登录(加验证码)
参考资料: https://blog.csdn.net/qq_34021712/article/details/80470738 ©王赛超
验证码校验:
@RequestMapping(value = "/login",method = RequestMethod.POST)
public String loginUser(HttpServletRequest request, String username, String password,boolean rememberMe,String captcha, Model model) {
//校验验证码
//session中的验证码
String sessionCaptcha = (String) SecurityUtils.getSubject().getSession().getAttribute(CaptchaController.KEY_CAPTCHA);
if (null == captcha || !captcha.equalsIgnoreCase(sessionCaptcha)) {
model.addAttribute("msg","验证码错误!");
return "login";
}
//对密码进行加密
//password=new SimpleHash("md5", password, ByteSource.Util.bytes(username.toLowerCase() + "shiro"),2).toHex();
//如果有点击 记住我
UsernamePasswordToken usernamePasswordToken=new UsernamePasswordToken(username,password,rememberMe);
//UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken(username,password);
Subject subject = SecurityUtils.getSubject();
try {
//登录操作
subject.login(usernamePasswordToken);
return "redirect:index";
} catch(Exception e) {
//登录失败从request中获取shiro处理的异常信息 shiroLoginFailure:就是shiro异常类的全类名
String exception = (String) request.getAttribute("shiroLoginFailure");
if(e instanceof UnknownAccountException){
model.addAttribute("msg","用户名或密码错误!");
}
if(e instanceof IncorrectCredentialsException){
model.addAttribute("msg","用户名或密码错误!");
}
if(e instanceof LockedAccountException){
model.addAttribute("msg","账号已被锁定,请联系管理员!");
}
//返回登录页面
return "login";
}
}
此处我将此模块放在logincontroller里面专门处理登录操作;下面的为验证码的生成;新建一个CaptchaUtil将它放在utils下面,标黄的地方注意是你自己定义的路径
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileOutputStream;
import java.util.Random;
import javax.imageio.ImageIO;
/**
* 验证码工具类
*/
public class CaptchaUtil {
// 随机产生的字符串
private static final String RANDOM_STRS = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
private static final String FONT_NAME = "Fixedsys";
private static final int FONT_SIZE = 18;
private Random random = new Random();
private int width = 80;// 图片宽
private int height = 25;// 图片高
private int lineNum = 50;// 干扰线数量
private int strNum = 4;// 随机产生字符数量
/**
* 生成随机图片
*/
public BufferedImage genRandomCodeImage(StringBuffer randomCode) {
// BufferedImage类是具有缓冲区的Image类
BufferedImage image = new BufferedImage(width, height,
BufferedImage.TYPE_INT_BGR);
// 获取Graphics对象,便于对图像进行各种绘制操作
Graphics g = image.getGraphics();
// 设置背景色
g.setColor(getRandColor(200, 250));
g.fillRect(0, 0, width, height);
// 设置干扰线的颜色
g.setColor(getRandColor(110, 120));
// 绘制干扰线
for (int i = 0; i <= lineNum; i++) {
drowLine(g);
}
// 绘制随机字符
g.setFont(new Font(FONT_NAME, Font.ROMAN_BASELINE, FONT_SIZE));
for (int i = 1; i <= strNum; i++) {
randomCode.append(drowString(g, i));
}
g.dispose();
return image;
}
/**
* 给定范围获得随机颜色
*/
private Color getRandColor(int fc, int bc) {
if (fc > 255){
fc = 255;
}
if (bc > 255){
bc = 255;
}
int r = fc + random.nextInt(bc - fc);
int g = fc + random.nextInt(bc - fc);
int b = fc + random.nextInt(bc - fc);
return new Color(r, g, b);
}
/**
* 绘制字符串
*/
private String drowString(Graphics g, int i) {
g.setColor(new Color(random.nextInt(101), random.nextInt(111), random
.nextInt(121)));
String rand = String.valueOf(getRandomString(random.nextInt(RANDOM_STRS
.length())));
g.translate(random.nextInt(3), random.nextInt(3));
g.drawString(rand, 13 * i, 16);
return rand;
}
/**
* 绘制干扰线
*/
private void drowLine(Graphics g) {
int x = random.nextInt(width);
int y = random.nextInt(height);
int x0 = random.nextInt(16);
int y0 = random.nextInt(16);
g.drawLine(x, y, x + x0, y + y0);
}
/**
* 获取随机的字符
*/
private String getRandomString(int num) {
return String.valueOf(RANDOM_STRS.charAt(num));
}
public static void main(String[] args) {
CaptchaUtil tool = new CaptchaUtil();
StringBuffer code = new StringBuffer();
BufferedImage image = tool.genRandomCodeImage(code);
System.out.println("random code = " + code);
try {
// 将内存中的图片通过流动形式输出到客户端
ImageIO.write(image, "JPEG", new FileOutputStream(new File(
"/Users/wangsaichao/Desktop/random-code.jpg")));
} catch (Exception e) {
e.printStackTrace();
}
}
}
登录界面的代码,如果是这样的话你会发现页面根本不会出现验证码,标黄部分是验证码刷新代码,你必须调用此方法来进行验证码的生成,标红部分为你的logincontroller里面的方法路径。
Insert title here
欢迎登录
然后说说我遇到的问题:账号密码输入正确但是登陆不了,原因就是shiro默认会将你的密码进行md5加密,匹配的时候要么将shiro的md5加密去掉,要么就是将密码进行md5加密后再进行匹配。shiro是不需要你进行数据库查找的,他默认的进行了这一操作。
3.第二个问题,普遍的跳转
方式有多种,这里只说的是controller里面的跳转:
@RequestMapping("/")
public String index() {
return "login";
}
@RequestMapping("/")
public String index() {
return "redirect:/login";
}
上述的两种跳转是比较多的,第一种,直接return,那么它是找的你的.jsp文件。第二种,redirect:/login解释为重定向,他会在controller里面找到相应的以RequestMapping("/login")为开头的方法。然后进行跳转。
另外的涉及到页面的相互传值的问题(跳转),以一个案例来分析
logincontroller里面
@RequestMapping("/edit")
public String userEdit(Model model, HttpServletRequest request) {
String id = request.getParameter("id");
int userid = Integer.parseInt(id);
方法
model.addAttribute("user", uservo);传值方式
return "页面";
}
@RequestMapping("/editUser")
@ResponseBody
public ResultVo edit(UserEntity userEntity) {
ResultVo result = new ResultVo();
方法
if (CommonUtil.isNotNull(userVo)) {
result.setSuccess(false);
} else {
result.setSuccess(true);
}
return result;
}
页面主要的ajax传值代码
$.ajax({
type: "POST",
async: "false",
dataType1: "json",
data : t,
url: "${root}/user/editUser", //传入值
success: function (data) {
if(data.success){
window.location.href ='${root}/edit'; //跳转界面
}
}
});
流程为:主页面加载完成:点击编辑按钮,在editUser里面进行判断,返回的result为true和false,如果返回为true则会跳转到edit,edit跳转到相应的页面。