RBAC

基于角色的权限访问控制(Role-Based Access Control)在RBAC中,权限与角色相关联,用户通过成为适当角色的成员而得到这些角色的权限。这就极大地简化了权限的管理。在一个组织中,角色是为了完成各种工作而创造,用户则依据它的责任和资格来被指派相应的角色,用户可以很容易地从一个角色被指派到另一个角色。角色可依新的需求和系统的合并而赋予新的权限,而权限也可根据需要而从某角色中回收。

在IEDA中,打开DATABASE菜单,连接数据库

一共5张表,很好理解,

用户和角色的关系:一个用户可以拥有多个角色,相反一个角色也可以被多个用户所拥有

角色和权限的关系:一个角色可以拥有多个权限,相反一个权限也可以被多个角色所拥有

建库和表的sql我这里就不贴了,好了,前期的配置到此就结束了,接下来下面正式进入开发之旅。。。。。。。。。。

//实现用户的登录--拦截认证--密码加密后验证登录

login.jsp

<%--
Created by IntelliJ IDEA.
User: shaojiang
Date: //
Time: 下午7:
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<meta name="renderer" content="webkit|ie-comp|ie-stand">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no" />
<meta http-equiv="Cache-Control" content="no-siteapp" />
<!--[if lt IE ]>
<script type="text/javascript" src="/statics/lib/html5shiv.js"></script>
<script type="text/javascript" src="/statics/lib/respond.min.js"></script>
<![endif]-->
<link href="/statics/h-ui/css/H-ui.min.css" rel="stylesheet" type="text/css" />
<link href="/statics/h-ui.admin/css/H-ui.login.css" rel="stylesheet" type="text/css" />
<link href="/statics/h-ui.admin/css/style.css" rel="stylesheet" type="text/css" />
<link href="/statics/lib/Hui-iconfont/1.0.8/iconfont.css" rel="stylesheet" type="text/css" />
<!--[if IE ]>
<script type="text/javascript" src="/statics/lib/DD_belatedPNG_0.0.8a-min.js" ></script>
<script>DD_belatedPNG.fix('*');</script>
<![endif]-->
<title>JavaEE权限管理系统</title>
<meta name="keywords" content="H-ui.admin v3.1,H-ui网站后台模版,后台模版下载,后台管理系统模版,HTML后台模版下载">
<meta name="description" content="H-ui.admin v3.1,是一款由国人开发的轻量级扁平化网站后台模板,完全免费开源的网站后台管理系统模版,适合中小型CMS后台系统。">
</head>
<body>
<input type="hidden" id="TenantId" name="TenantId" value="" />
<div class="header">JavaEE权限管理系统</div>
<div class="loginWraper">
<div id="loginform" class="loginBox">
<form id="login_form1" class="form form-horizontal" onsubmit="return false" action="##" method="post">
<div style="color: red;text-align: center;">${requestScope.loginError}</div>
<div class="row cl">
<label class="form-label col-xs-3"><i class="Hui-iconfont"></i></label>
<div class="formControls col-xs-8">
<input id="userName" name="userName" type="text" placeholder="账户" class="input-text size-L">
</div>
</div>
<div class="row cl">
<label class="form-label col-xs-3"><i class="Hui-iconfont"></i></label>
<div class="formControls col-xs-8">
<input id="password" name="password" type="password" placeholder="密码" class="input-text size-L">
</div>
</div>
<%--<div class="row cl">--%>
<%--<div class="formControls col-xs-8 col-xs-offset-3">--%>
<%--<input class="input-text size-L" type="text" placeholder="验证码" onblur="if(this.value==''){this.value='验证码:'}" onclick="if(this.value=='验证码:'){this.value='';}" value="验证码:" style="width:150px;">--%>
<%--<img src=""> <a id="kanbuq" href="javascript:;">看不清,换一张</a> </div>--%>
<%--</div>--%>
<div class="row cl">
<div class="formControls col-xs-8 col-xs-offset-3">
<label for="rememberMe">
<input type="checkbox" name="rememberMe" id="rememberMe" value="">
使我保持登录状态</label>
</div>
</div>
<div class="row cl">
<div class="formControls col-xs-8 col-xs-offset-3">
<input id="sub_login" name="" type="button" class="btn btn-success radius size-L" value="&nbsp;登&nbsp;&nbsp;&nbsp;&nbsp;录&nbsp;">
<%--<input name="" type="reset" class="btn btn-default radius size-L" value="&nbsp;取&nbsp;&nbsp;&nbsp;&nbsp;消&nbsp;">--%>
</div>
</div>
</form>
</div>
</div>
<div class="footer">Copyright 通用权限管理系统 by H-ui.admin v3.</div>
<script type="text/javascript" src="/statics/lib/jquery/1.9.1/jquery.min.js"></script>
<script type="text/javascript" src="/statics/h-ui/js/H-ui.min.js"></script>
<script type="text/javascript" src="/statics/lib/layer/2.4/layer.js"></script>
<script type="text/javascript"> //当登录超时,会跳转到登录页面,如果在框架中加载了登录页,首先进行判断,如果不是顶级路径,就导致顶级路径
if (window.top!=window.self) {
//alert("执行了");
window.top.location.href = '/admin/login';
} $(function()
{ // 读取cookies中的用户信息
var rem = $.cookie('rememberMe');
if(rem){
$("#rememberMe").prop("checked",true);
$("#userName").val($.cookie("username"));
$("#password").val($.cookie("password"));
} //登录
$("#sub_login").click(function () { var username = $("#userName").val();
var password = $("#password").val(); if(!username){
layer.msg("请输入用户名");
$("#userName").focus().select();
return false;
}else if(!password){
layer.msg("请输入登录密码");
$("#password").focus().select();
return false;
}else
{
//验证是否需要保存账户信息到cookies
saveCookies();
//alert($('#login_form1').serialize());
//登录系统
$.ajax({
//几个参数需要注意一下
type: "POST",//方法类型
dataType: "json",//预期服务器返回的数据类型
url: "/admin/login" ,//url
data: $('#login_form1').serialize(),
success: function (data) {
console.log(data.result);//打印服务端返回的数据(调试用)
if (data.result == 'SUCCESS'||data.result == ) {
window.location.href = "/admin/main";
}else
{
layer.msg("登录失败:"+data.result.toString(),{icon:,time:});
}
},
error : function() {
layer.msg(data.result.toString());
}
}); } });
}); /**
* jquery.cookie.js 是一个轻量级的cookie 插件,可以读取、写入、删除 cookie。
* H-ui.js 中已封装jquery.cookie.js,无需单独下载。
*/
function saveCookies() { if($("#rememberMe").is(":checked")){
//alert("记住我");
var username = $("#userName").val();
var password = $("#password").val(); //创建一个cookie并设置有效时间为 7天:
//如果没有指定有效期,所创建的cookie有效期默认到用户关闭浏览器为止
$.cookie("rememberMe","true",{expires:});
$.cookie("username",username,{expires: });
$.cookie("password",password,{expires: });
}else{
$.cookie("rememberMe","false",{expires:-});
$.cookie("username","",{ expires:- });
$.cookie("password","",{ expires:- });
}
} </script>
</body>
</html>

AdminController

    /**
* 管理员登录
* @return
*/
@RequestMapping(value = "/login",method = RequestMethod.POST)
@ResponseBody
public Map<String,Object> adminLogin(
HttpServletRequest request,
HttpSession session)
{
Map<String,Object> resultMap = new HashMap<String,Object>(); if(request.getParameter("userName")==null||
request.getParameter("password")==null){
resultMap.put("result","用户名或密码不能为空");
} //获取用户名和密码
String userName = request.getParameter("userName").toString();
String password = request.getParameter("password").toString(); //查询数据库该用户是否存在
AdminUser adminUser = adminUserService.findAdminUserByLoginName(userName); if(adminUser!=null){
//logger.info("adminUser:"+adminUser.toString());
//将用户的密码进行加密后返回,再进行比对
String encryptPassword =
passwordEncryption.encryption(password,
adminUser.getLoginName().toString());
if(adminUser.getLoginName().equals(userName)&&
adminUser.getPassword().equals(encryptPassword))
{
if(adminUser.getState()==){
//验证通过,保存登录信息到session,转发到管理员后台控制器
session.setAttribute("adminUser",adminUser);
resultMap.put("result","SUCCESS");
}else
{
resultMap.put("result","账户异常!请联系系统管理员!");
}
}else
{
resultMap.put("result","用户名或密码错误!");
}
}else
{
resultMap.put("result","用户名不存在!");
} return resultMap;
}

登录时用到了passwordEncryption服务类,该类负责进行密码的加密,当用户登录时,将用户的密码进行加密,这里加密的规则,是把当前用户名作为盐值,使用sha-256算法,散列次数5,进行加密,加密后,再使用Base64进行编码,加密后根据当前登录的用户名查询该用户的数据库储存的加密密码比对是否一致,如果一致,登录成功。

使用自动注入引用

@Autowired
private PasswordEncryption passwordEncryption;

我是放在了service子模块中的,这样子方便扫描

PasswordEncryption类:

package com.supin51.service.impl;

import org.apache.shiro.crypto.hash.SimpleHash;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service; import java.io.Serializable; /**
* @Author:ShaoJiang
* @description: apache shiro 的SimpleHash工具类加密
* @Date: created in 上午10:57 2019/1/26
* @Modified By:
*/
@Service
public class PasswordEncryption{ /**
* 基于注解的装配,这样可以在encrypt.properties属性文件中更改配置,在这里使用@Value进行注解装配获取到值
   * 后期如果需要更改加密类型,可在属性文件中更改其他算法:md5,sha1,sha-128,sha-256,sha-512
* 使用@Value的类,在spring中,不能直接通过new 操作符来使用,这样获取不到值的
* 而是在需要使用的地方,通过spring的注解 @Autowired 来使用,
* 例如:@Autowired private PasswordEncryption passwordEncryption;
*/
@Value("${algorithmName}")
private String algorithmName;//加密算法,md5,sha1,sha-128,sha-256,sha-512
@Value("${hashIterations}")
private int hashIterations;//散列次数
@Value("${isHex}")
private boolean isHex;//是否使用十六进制编码,设置false后将启用Base64编码 /**
* 密码加密
* @param password 加密前的密码
* @param salt 盐值(传递当前的用户名用作盐值)
* @return
*/
public String encryption(String password, String salt)
{
String encryptStr = "";
if(isHex)
{
//使用十六进制进行编码
//带salt(盐值)和散列加密后,再用十六进制编码
encryptStr =
new SimpleHash(algorithmName,password,salt,hashIterations).toHex();
//System.out.print("十六进制编码");
}else
{
//使用Base64进行编码
//带salt(盐值)和散列加密后,再用Base64编码
encryptStr =
new SimpleHash(algorithmName,password,salt,hashIterations).toBase64();
//System.out.print("Base64编码");
}
return encryptStr;
} }

应为拦截了所有路径,所以还要添加认证拦截器:

AuthenticationInterceptor类:

package com.supin51.interceptor;

import com.supin51.domain.AdminUser;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; /**
* @Author:ShaoJiang
* @description:登录认证拦截
* @Date: created in 下午8:18 2019/1/21
* @Modified By:
*/
public class AuthenticationInterceptor implements HandlerInterceptor { private static final Log logger = LogFactory.getLog(AuthenticationInterceptor.class); //定义不需要拦截的URL路径
private static final String[] NO_INTERCEPTOR_URL = {"/admin/login","/404","/favicon.ico"}; /*
* return true 才会继续执行下列两个方法(请求继续),否则整个请求结束
* 该方法主要进行拦截处理,该方法在Controller处理之前调用,
* */
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { boolean flag = false;
//获取请求的路径进行判断
String servletUrl = request.getServletPath();
logger.info("url认证拦截器:preHandle-------->"+servletUrl);
//循环拦截的URL路径,如果当前请求的URL中包含需要拦截的URL,返回true
for (String s :NO_INTERCEPTOR_URL)
{
if(servletUrl.contains(s)){ flag = true;
break;
}
} //拦截请求
if(!flag){
//获取session中的用户信息
AdminUser adminUser = (AdminUser)request.getSession().getAttribute("adminUser");
//如果用户已登录,放行,否则拦截
if(adminUser!=null){
logger.info("url认证拦截器:preHandle-------->用户已登录,放行请求-------->");
flag = true;
}else
{
logger.info("url认证拦截器:preHandle-------->用户未登录,拦截请求-------->"); request.setAttribute("message","登录信息失效,请重新登录");
//只适合跳转页面,URL地址保持不变
//request.getRequestDispatcher("user1/login").forward(request,response);
response.sendRedirect("/admin/login");//重定向到控制器,URL地址改变
}
} return flag;
} @Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
logger.info("url认证拦截器:postHandle-------->");
} @Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
logger.info("url认证拦截器:afterCompletion-------->");
}
}

至此,整个登录的实现流程结束。本小节结束,下一小节将实现,登录成功后的权限菜单显示,基于自定义注解方法级别的权限菜单的拦截验证。

 

最新文章

  1. 在thinkphp中,写的博文标签多对多关系的标签频率统计算法
  2. servlet 之request
  3. 深入理解CSS浮动
  4. springMVC的@ResponseBody、@RequestBody使用需要注意的地方
  5. Linux命令学习-mpstat
  6. Common Lisp编译程序的小技巧
  7. [ZETCODE]wxWidgets教程四:菜单栏和工具栏
  8. Oracle数据库top10物理段
  9. WebxFrameworkFilter 请求响应过程
  10. RF常用技巧随笔
  11. php安全编程&amp;python测试实例编写
  12. CSS魔法堂:改变单选框颜色就这么吹毛求疵!
  13. CF886C Petya and Catacombs
  14. Redis无法启动
  15. 利用ML&amp;AI判定未知恶意程序——里面提到ssl恶意加密流检测使用N个payload CNN + 字节分布包长等特征综合判定
  16. 《SQL Server 2008从入门到精通》--20180704
  17. 使用免安装压缩包安装MySQL
  18. sql 命令使用简单记录
  19. 最大开源代码sourceforge 简介 及视音频方面常用的开源代码
  20. HDU 2489 Minimal Ratio Tree(暴力+最小生成树)(2008 Asia Regional Beijing)

热门文章

  1. nyoj 1023——还是回文——————【区间dp】
  2. PHP配置错误信息回报的等级
  3. 我们能用canvas做什么?
  4. 在List中常用的linq表达式
  5. .net编程知识点
  6. net2.0实现net3.5特性,如扩展方法,Linq等
  7. jeecg308 &lt;t:authFilter /&gt;标签失效的问题
  8. 重构指南 - 移除重复内容(Remove Duplication)
  9. 记升级一次的http2学习
  10. canvas入门(一)