http://www.oschina.net/code/snippet_133989_32527
上门链接是上次分享了在jfinal中添加jcaptcha验证码
后看到@玛雅牛的jfinal-shiro插件,顺便将验证码加入
MyShiroRealm.java
/**
* 认证回调函数, 登录时调用.
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authcToken) throws AuthenticationException {
//是否启用验证码
if (useCaptcha) {
CaptchaUsernamePasswordToken token = (CaptchaUsernamePasswordToken) authcToken;
String parm = token.getCaptcha();
if (StringUtils.isNotBlank(parm))
parm = parm.toUpperCase();
try {
if (!CaptchaServiceSingleton.getInstance().validateResponseForID(SecurityUtils
.getSubject().getSession().getId().toString(), parm)) {
throw new IncorrectCaptchaException("验证码错误!");
}
} catch (Exception e) {
// session如果没有刷新,validateResponseForID会抛出com.octo.captcha.service.CaptchaServiceException的异常
throw new IncorrectCaptchaException("验证码错误!");
}
}
UsernamePasswordToken token = (UsernamePasswordToken) authcToken;
String password = String.valueOf(token.getPassword());
// 调用操作数据库的方法查询user信息
User user = User.dao.getUserByName(token.getUsername());
if (user != null) {
byte[] salt = Encodes.decodeHex(user.getStr(User.SALT));
List<Role> roles = Role.dao.getRoleByUser(user.getStr(User.ID));
ShiroUser shiroUser = new ShiroUser(user.getStr(User.ID), user.getStr(User.USERNAME), user,roles);
Session session = SecurityUtils.getSubject().getSession();
session.setAttribute(SecurityConstants.LOGIN_USER, shiroUser);
// 这里可以缓存认证
return new SimpleAuthenticationInfo(shiroUser, user.getStr(User.PASSWORD),
ByteSource.Util.bytes(salt), getName());
} else {
return null;
}
}
view-login.ftl
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta charset="utf-8">
<title>登录</title>
<meta content="IE=edge,chrome=1" http-equiv="X-UA-Compatible">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="">
<meta name="author" content="">
<link rel="stylesheet" type="text/css" href="${CONTEXT_PATH}/resources/bootstrap/css/bootstrap.css">
<script src="${CONTEXT_PATH}/resources/js/jquery.js" type="text/javascript"></script>
<script src="${CONTEXT_PATH}/resources/js/jquery-validation/jquery.validate.min.js" type="text/javascript"></script>
<script src="${CONTEXT_PATH}/resources/js/jquery-validation/jquery.metadata.js" type="text/javascript"></script>
<script src="${CONTEXT_PATH}/resources/js/jquery-validation/messages_cn.js" type="text/javascript"></script>
<link rel="stylesheet" type="text/css" href="${CONTEXT_PATH}/resources/css/theme.css">
<!-- Le HTML5 shim, for IE6-8 support of HTML5 elements -->
<!--[if lt IE 9]>
<script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
<script type="text/javascript">
$(function (){
$("#signupForm").validate({
rules: {
username: "required",
captcha_key: "required",
password: {
required: true,
minlength: 5
}
},
messages: {
username: "请输入用户名",
captcha_key: "请输入验证码",
password: {
required: "请输入密码",
minlength: jQuery.format("密码不能小于{0}个字 符")
}
}
});
});
</script>
<style type="text/css">
input.error { border: 1px solid red; }
label.error {
padding-left: 16px;
padding-bottom: 2px;
font-weight: bold;
color: #EA5200;
}
</style>
</head>
<!--[if lt IE 7 ]> <body class="ie ie6"> <![endif]-->
<!--[if IE 7 ]> <body class="ie ie7 "> <![endif]-->
<!--[if IE 8 ]> <body class="ie ie8 "> <![endif]-->
<!--[if IE 9 ]> <body class="ie ie9 "> <![endif]-->
<!--[if (gt IE 9)|!(IE)]><!-->
<body class="">
<div class="row-fluid login">
<div class="dialog">
<p class="brand" href="${CONTEXT_PATH}/admin/">CMS.</p>
<div class="block">
<div class="block-header">
<h2>登录</h2>
</div>
<form id="signupForm" action="${CONTEXT_PATH}/admin/validateLogin" method="post">
<label>用户名</label>
<input type="text" class="span12" name="username"/>
<label class="error" for="username" generated="true"></label>
<label>密码</label>
<input type="password" class="span12" name="password"/>
<label class="error" for="password" generated="true"></label>
<label>验证码</label>
<input type="text" id="captcha_key" name="captcha_key" class="login_input" style="width:85px">
<img src="${CONTEXT_PATH}/admin/random_code" id="captcha" title="点击更换图片"/>
<label class="error" for="password" generated="true"></label>
<div class="form-actions">
<input value="登 录" class="btn btn-success pull-right" type="submit"/>
<div class="clearfix"></div>
</div>
<#if shiroLoginFailure?exists>
<#assign error=shiroLoginFailure/>
</#if>
<#if error?exists>
<div id="message" class="alert alert-block alert-error">
<button type="button" class="close" data-dismiss="alert"></button>
<strong>Warning!</strong>
<#if error?contains("AuthenticationException")>
请检查您输入的账户、密码、验证码是否正确.
<#elseif error?contains("UnknownAccountException")>
请检查您输入的账户、密码、验证码是否正确.
<#elseif error?contains("DisabledAccountException")>
未经审核的账户不允许登录.
<#elseif error?contains("IncorrectCaptchaException")>
验证码错误.
<#else>
登录失败,请重试.
</#if>
</div>
</#if>
</form>
</div>
</div>
</div>
<script>
jQuery(document).ready(function() {
$("#username").focus();
//验证码点击时显示
$('#captcha').click(function(){
$('#captcha').attr("src","${CONTEXT_PATH}/admin/random_code?seed="+Math.random());
});
});
</script>
</body>
</html>
@ControllerBind(controllerKey="/admin/validateLogin")
@Before(AdminInterceptorStack.class)
public class LoginController extends Controller {
private Collection<Module> moduleSets = new TreeSet<Module>();
//主页
public void index() throws Exception{
String username = getPara(CaptchaFormAuthenticationFilter.DEFAULT_USERNAME_PARAM);
setAttr(CaptchaFormAuthenticationFilter.DEFAULT_USERNAME_PARAM, username);
// render(IndexController.LOGIN_PAGE);
returnTo(this,Constants.NO_LOGIN, getRequest(),getResponse());
}
private void returnTo(Controller controller,String result, HttpServletRequest request,
HttpServletResponse response) throws IOException {
if (AJAXResponseUtils.isAjaxRequest(request)) {
AJAXResponseUtils.response(controller,response, Constants.NO_LOGIN);
}else if(Constants.NO_LOGIN.equals(result)){
controller.render(Constants.LOGIN_PAGE);
}else{
controller.render(result);
}
}
}