基于权限安全框架Shiro的登录验证功能实现
2017-10-22 01:21
1296 查看
目前在企业级项目里做权限安全方面喜欢使用Apache开源的Shiro框架或者Spring框架的子框架Spring Security。
Apache Shiro是一个强大且易用的Java安全框架,执行身份验证、授权、密码学和会话管理。
Shiro框架具有轻便,开源的优点,所以本博客介绍基于Shiro的登录验证实现。
在maven里加入shiro需要的jar
在web.xml加上Shiro过滤器配置:
编写shiro的ShiroRealm类:
在Spring框架里集成Shiro,加入配置
登录验证控制类实现:
前端Ajax和JQeury校验实现:
登录成功,Session会话过期,需要重新登录,保证系统安全性
本博客只提供基于Shiro的登录验证实现,具体代码可以去我的github下载:https://github.com/u014427391/jeeplatform
欢迎star
Apache Shiro是一个强大且易用的Java安全框架,执行身份验证、授权、密码学和会话管理。
Shiro框架具有轻便,开源的优点,所以本博客介绍基于Shiro的登录验证实现。
在maven里加入shiro需要的jar
<!--shiro start--> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-all</artifactId> <version>1.2.3</version> </dependency> <!-- shiro end-->
在web.xml加上Shiro过滤器配置:
<!-- Shiro过滤器配置 start --> <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> <!-- Shiro过滤器配置 end -->
编写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 { /**注解引入业务类**/ @Resource UserService userService; /** * 登录信息和用户验证信息验证(non-Javadoc) * @see org.apache.shiro.realm.AuthenticatingRealm#doGetAuthenticationInfo(AuthenticationToken) */ @Override protected 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) */ @Override protected 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; } @Override public void clearCachedAuthorizationInfo(PrincipalCollection principals) { super.clearCachedAuthorizationInfo(principals); } @Override public void clearCachedAuthenticationInfo(PrincipalCollection principals) { super.clearCachedAuthenticationInfo(principals); } @Override public void clearCache(PrincipalCollection principals) { super.clearCache(principals); } }
在Spring框架里集成Shiro,加入配置
<!-- Shiro start --> <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager"> <property name="realm" ref="ShiroRealm" /> </bean> <!-- 项目自定义的Realm --> <bean id="ShiroRealm" class="org.muses.jeeplatform.core.security.shiro.ShiroRealm" ></bean> <!-- Shiro Filter --> <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean"> <property name="securityManager" ref="securityManager" /> <property name="loginUrl" value="/login" /> <property name="successUrl" value="/admin/index" /> <property name="unauthorizedUrl" value="/login" /> <property name="filterChainDefinitions"> <value> /static/** = anon /upload/** = anon /plugins/** = anon /code = anon /login = anon /logincheck = anon /** = authc </value> </property> </bean> <!-- Shiro end -->
登录验证控制类实现:
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 { @Autowired UserService userService; @Autowired MenuService menuService; /** * 获取登录用户的IP * @throws Exception */ public void getRemortIP(String username) { HttpServletRequest request = this.getRequest(); Map<String,String> map = new HashMap<String,String>(); String ip = ""; if (request.getHeader("x-forwarded-for") == null) { ip = request.getRemoteAddr(); }else{ ip = request.getHeader("x-forwarded-for"); } map.put("username", username); map.put("loginIp", ip); userService.saveIP(map); } /** * 访问后台登录页面 * @return * @throws Exception */ @RequestMapping(value="/login",produces="text/html;charset=UTF-8") public ModelAndView toLogin()throws ClassNotFoundException{ ModelAndView mv = this.getModelAndView(); mv.setViewName("admin/frame/login"); return mv; } /** * 基于Shiro框架的登录验证,页面发送JSON请求数据, * 服务端进行登录验证之后,返回Json响应数据,"success"表示验证成功 * @param request * @return * @throws Exception */ @RequestMapping(value="/logincheck", produces="application/json;charset=UTF-8") @ResponseBody public String loginCheck(HttpServletRequest request)throws AuthenticationException{ JSONObject obj = new JSONObject(); String errInfo = "";//错误信息 String logindata[] = request.getParameter("LOGINDATA").split(","); if(logindata != null && logindata.length == 3){ //获取Shiro管理的Session Subject subject = SecurityUtils.getSubject(); Session session = subject.getSession(); String codeSession = (String)session.getAttribute(Constants.SESSION_SECURITY_CODE); String code = logindata[2]; /**检测页面验证码是否为空,调用工具类检测**/ if(Tools.isEmpty(code)){ errInfo = "nullcode"; }else{ String username = logindata[0]; String password = logindata[1]; if(Tools.isNotEmpty(codeSession) && codeSession.equalsIgnoreCase(code)){ //Shiro框架SHA加密 String passwordsha = new SimpleHash("SHA-1",username,password).toString(); System.out.println(passwordsha); //检测用户名和密码是否正确 User user = userService.doLoginCheck(username,passwordsha); if(user != null){ if(Boolean.TRUE.equals(user.getLocked())){ errInfo = "locked"; }else{ //Shiro添加会话 session.setAttribute("username", username); session.setAttribute(Constants.SESSION_USER, user); //删除验证码Session session.removeAttribute(Constants.SESSION_SECURITY_CODE); //保存登录IP getRemortIP(username); /**Shiro加入身份验证**/ Subject sub = SecurityUtils.getSubject(); UsernamePasswordToken token = new UsernamePasswordToken(username,password); sub.login(token); } }else{ //账号或者密码错误 errInfo = "uerror"; } if(Tools.isEmpty(errInfo)){ errInfo = "success"; } }else{ //缺少参数 errInfo="codeerror"; } } } obj.put("result", errInfo); return obj.toString(); } /** * 后台管理系统主页 * @return * @throws Exception */ @RequestMapping(value="/admin/index") public ModelAndView toMain() throws AuthenticationException{ ModelAndView mv = this.getModelAndView(); /**获取Shiro管理的Session**/ Subject subject = SecurityUtils.getSubject(); Session session = subject.getSession(); User user = (User)session.getAttribute(Constants.SESSION_USER); if(user != null){ ...//业务实现 }else{ //会话失效,返回登录界面 mv.setViewName("admin/frame/login"); } mv.setViewName("admin/frame/index"); return mv; } /** * 注销登录 * @return */ @RequestMapping(value="/logout") public ModelAndView logout(){ ModelAndView mv = this.getModelAndView(); /**Shiro管理Session**/ Subject sub = SecurityUtils.getSubject(); Session session = sub.getSession(); session.removeAttribute(Constants.SESSION_USER); session.removeAttribute(Constants.SESSION_SECURITY_CODE); /**Shiro销毁登录**/ Subject subject = SecurityUtils.getSubject(); subject.logout(); /**返回后台系统登录界面**/ mv.setViewName("admin/frame/login"); return mv; } }
前端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",//请求方式为POST url: 'logincheck',//检验url data: {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
相关文章推荐
- 基于权限安全框架Shiro的登录验证功能实现
- shiro框架---关于用户登录和权限验证功能的实现步骤(三)
- shiro框架---关于用户登录和权限验证功能的实现步骤(七)
- shiro框架---关于用户登录和权限验证功能的实现步骤(四)
- shiro框架---关于用户登录和权限验证功能的实现步骤(五)
- spring boot配置shiro安全框架及用户登录权限验证实现
- shiro框架---关于用户登录和权限验证功能的实现步骤(八)
- shiro框架---关于用户登录和权限验证功能的实现步骤(一)
- shiro框架---关于用户登录和权限验证功能的实现步骤(六)
- shiro框架---关于用户登录和权限验证功能的实现步骤(二)
- 简单两步快速实现shiro的配置和使用,包含登录验证、角色验证、权限验证以及shiro登录注销流程(基于spring的方式,使用maven构建)
- PHP实现用户异地登录提醒功能的方法【基于thinkPHP框架】
- SpringMVC+Apache Shiro+JPA(hibernate)案例教学(二)基于SpringMVC+Shiro的用户登录权限验证
- Shiro安全框架入门篇(登录验证实例详解与源码)
- Shiro安全框架入门篇(登录验证实例详解与源码)
- 简单两步快速实现shiro的配置和使用,包含登录验证、角色验证、权限验证以及shiro登录注销流程
- shiro 权限控制框架 入门级实例(一)加密、登录验证
- SpringMVC+Apache Shiro+JPA(hibernate)案例教学(二)基于SpringMVC+Shiro的用户登录权限验证
- Shiro安全框架入门篇(登录验证实例详解与源码)
- Shiro安全框架入门篇(登录验证实例详解与源码)