目前在企业级项目里做权限安全方面喜欢使用Apache开源的Shiro框架或者Spring框架的子框架Spring Security。
Apache Shiro是一个强大且易用的Java安全框架,执行身份验证、授权、密码学和会话管理。
Shiro框架具有轻便,开源的优点,所以本博客介绍基于Shiro的登录验证实现。
在maven里加入shiro需要的jar
在web.xml加上Shiro过滤器配置:
编写shiro的ShiroRealm类:
package org.muses.jeeplatform.core.security.shiro;import javax.annotation.Resource;import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.LockedAccountException;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UnknownAccountException;
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.muses.jeeplatform.model.entity.User;
import org.muses.jeeplatform.service.UserService;/*** @description 基于Shiro框架的权限安全认证和授权* @author Nicky* @date 2017年3月12日*/
public class ShiroRealm extends AuthorizingRealm {/**注解引入业务类**/@ResourceUserService userService;/*** 登录信息和用户验证信息验证(non-Javadoc)* @see org.apache.shiro.realm.AuthenticatingRealm#doGetAuthenticationInfo(AuthenticationToken)*/@Overrideprotected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {String username = (String)token.getPrincipal(); //得到用户名 String password = new String((char[])token.getCredentials()); //得到密码User user = userService.findByUsername(username);/**检测是否有此用户 **/if(user == null){throw new UnknownAccountException();//没有找到账号异常}/**检验账号是否被锁定 **/if(Boolean.TRUE.equals(user.getLocked())){throw new LockedAccountException();//抛出账号锁定异常}/**AuthenticatingRealm使用CredentialsMatcher进行密码匹配**/if(null != username && null != password){return new SimpleAuthenticationInfo(username, password, getName());}else{return null;}}/*** 授权查询回调函数, 进行鉴权但缓存中无用户的授权信息时调用,负责在应用程序中决定用户的访问控制的方法(non-Javadoc)* @see AuthorizingRealm#doGetAuthorizationInfo(PrincipalCollection)*/@Overrideprotected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection pc) {String username = (String)pc.getPrimaryPrincipal();SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();authorizationInfo.setRoles(userService.getRoles(username));authorizationInfo.setStringPermissions(userService.getPermissions(username));System.out.println("Shiro授权");return authorizationInfo;}@Overridepublic void clearCachedAuthorizationInfo(PrincipalCollection principals) {super.clearCachedAuthorizationInfo(principals);}@Overridepublic void clearCachedAuthenticationInfo(PrincipalCollection principals) {super.clearCachedAuthenticationInfo(principals);}@Overridepublic void clearCache(PrincipalCollection principals) {super.clearCache(principals);}}
在Spring框架里集成Shiro,加入配置
登录验证控制类实现:
package org.muses.jeeplatform.web.controller;import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;import javax.servlet.http.HttpServletRequest;import net.sf.json.JSONArray;
import net.sf.json.JSONObject;import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.crypto.hash.SimpleHash;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.Subject;
import org.muses.jeeplatform.core.Constants;
import org.muses.jeeplatform.model.entity.Menu;
import org.muses.jeeplatform.model.entity.Permission;
import org.muses.jeeplatform.model.entity.Role;
import org.muses.jeeplatform.model.entity.User;
import org.muses.jeeplatform.service.MenuService;
import org.muses.jeeplatform.service.UserService;
import org.muses.jeeplatform.utils.Tools;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;/*** @description 登录操作的控制类,使用Shiro框架,做好了登录的权限安全认证,* getRemortIP()方法获取用户登录时的ip并保存到数据库* @author Nicky* @date 2017年3月15日*/
@Controller
public class LoginController extends BaseController {@AutowiredUserService userService;@AutowiredMenuService menuService;/*** 获取登录用户的IP* @throws Exception */public void getRemortIP(String username) { HttpServletRequest request = this.getRequest();Map
前端Ajax和JQeury校验实现:
/**客户端校验**/function checkValidity() {if ($("#username").val() == "") {$("#username").tips({side : 2,msg : '用户名不得为空',bg : '#AE81FF',time : 3});$("#username").focus();return false;}if ($("#password").val() == "") {$("#password").tips({side : 2,msg : '密码不得为空',bg : '#AE81FF',time : 3});$("#password").focus();return false;}if ($("#code").val() == "") {$("#code").tips({side : 1,msg : '验证码不得为空',bg : '#AE81FF',time : 3});$("#code").focus();return false;}return true;}/**服务器校验**/function loginCheck(){if(checkValidity()){var username = $("#username").val();var password = $("#password").val();var code = username+","+password+","+$("#code").val();$.ajax({type: "POST",//请求方式为POSTurl: 'logincheck',//检验urldata: {LOGINDATA:code,tm:new Date().getTime()},//请求数据dataType:'json',//数据类型为JSON类型cache: false,//关闭缓存success: function(data){//响应成功if("success" == data.result){$("#login").tips({side : 1,msg : '正在登录 , 请稍后 ...',bg : '#68B500',time : 10});window.location.href="admin/index";}else if("uerror" == data.result){$("#username").tips({side : 1,msg : "用户名或密码有误",bg : '#FF5080',time : 15});$("#username").focus();}else if("codeerror" == data.result){$("#code").tips({side : 1,msg : "验证码输入有误",bg : '#FF5080',time : 15});$("#code").focus();}else if("locked" == data.result){alert('您的账号被锁定了,呜呜');}else{$("#username").tips({side : 1,msg : "缺少参数",bg : '#FF5080',time : 15});$("#username").focus();}}});}}
登录成功,Session会话过期,需要重新登录,保证系统安全性
本博客只提供基于Shiro的登录验证实现,具体代码可以去我的github下载:https://github.com/u014427391/jeeplatform
欢迎star