Oracle创建表空间,用户及授权
--创建表空间
create tablespace jk
datafile 'E:\Develop_Index\oraclePlace\jkP\jkP.dbf'
size 50M
autoextend on
next 10M
--创建用户
create user heima
identified by heima
default tablespace jk
--授权
grant dba to heima
--或者授权
grant connect,resource to heima
分页实现说明
代码
/**
* 分页辅助类:对分页的基本数据进行一个简单的封装 用来传递分页参数和查询参数params
*/
public class Page<T> {
private int pageNo = 1; // 页码,默认是第一页
private int pageSize = SysConstant.PAGE_SIZE; // 每页显示的记录数,默认是10
private int totalRecord; // 总记录数
private int totalPage; // 总页数
private List<T> results; // 对应的当前页记录
private Map<String, Object> params = new HashMap<String, Object>(); // 其他的参数我们把它分装成一个Map对象
public int getPageNo() {
return pageNo;
}
public void setPageNo(int pageNo) {
this.pageNo = pageNo;
}
public int getPageSize() {
return pageSize;
}
public void setPageSize(int pageSize) {
this.pageSize = pageSize;
}
public int getTotalRecord() {
return totalRecord;
}
public void setTotalRecord(int totalRecord) {
this.totalRecord = totalRecord;
// 在设置总页数的时候计算出对应的总页数,在下面的三目运算中加法拥有更高的优先级,所以最后可以不加括号。
int totalPage = totalRecord % pageSize == 0 ? totalRecord / pageSize : totalRecord / pageSize + 1;
this.setTotalPage(totalPage);
}
public int getTotalPage() {
return totalPage;
}
public void setTotalPage(int totalPage) {
this.totalPage = totalPage;
}
public List<T> getResults() {
return results;
}
public void setResults(List<T> results) {
this.results = results;
}
public Map<String, Object> getParams() {
return params;
}
public void setParams(Map<String, Object> params) {
this.params = params;
}
public String toString() {
StringBuilder builder = new StringBuilder();
builder.append("Page [pageNo=").append(pageNo).append(", pageSize=").append(pageSize).append(", results=")
.append(results).append(", totalPage=").append(totalPage).append(", totalRecord=").append(totalRecord)
.append("]");
return builder.toString();
}
/* 页面链接 */
public String url; // 分页按钮中的转向链接
public void setUrl(String url) {
this.url = url;
}
public String links;
public String getLinks() {
StringBuffer sBuf = new StringBuffer();
int curPageNo = this.pageNo; // 当前页
sBuf.append("<span class=\"noprint\" style=\"padding:5px;\">");
// 利用js动态设置分页页码
sBuf.append("<script language=\"javascript\">");
sBuf.append(" function setPageNo( value ){");
sBuf.append(" document.getElementById(\"page.pageNo\").value = value;");
// sBuf.append(" alert(document.getElementById(\"pageNo\").value);");
sBuf.append(" }");
sBuf.append("</script>");
sBuf.append("<input type=\"hidden\" id=\"page.pageNo\" name=\"page.pageNo\" value=\"").append(curPageNo)
.append("\">"); // 分页参数:当前页隐藏域
sBuf.append(" 第").append(curPageNo).append("页 / 共").append(this.totalPage).append("页 ");
sBuf.append(" 总共").append(this.totalRecord).append("条记录 每页").append(this.pageSize).append("条记录 ");
sBuf.append("<a href=\"#").append("\" οnclick=\"setPageNo(1);formSubmit('").append(url).append("','_self')");
sBuf.append("\">[首页]");
sBuf.append("</a> ");
if (this.pageNo <= 1) {
curPageNo = 1;
} else {
curPageNo = this.pageNo - 1;
}
sBuf.append("<a href=\"#").append("\" οnclick=\"setPageNo(").append(curPageNo).append(");formSubmit('")
.append(url).append("','_self')");
sBuf.append("\">[上一页]");
sBuf.append("</a> ");
if (this.pageNo >= this.totalPage) {
curPageNo = this.totalPage;
} else {
curPageNo = this.pageNo + 1;
}
sBuf.append("<a href=\"#").append("\" οnclick=\"setPageNo(").append(curPageNo).append(");formSubmit('")
.append(url).append("','_self')");
sBuf.append("\">[下一页]");
sBuf.append("</a> ");
sBuf.append("<a href=\"#").append("\" οnclick=\"setPageNo(").append(this.totalPage).append(");formSubmit('")
.append(url).append("','_self')");
sBuf.append("\">[末页]");
sBuf.append("</a> ");
sBuf.append("</span>");
return sBuf.toString();
}
}
Shiro框架的应用 登陆验证授权及权限控制
权限相关7张表
pom jar包引用
<!-- shiro -->
<!-- apache shiro dependencies -->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-all</artifactId>
<version>${shiro.version}</version>
</dependency>
web.xml
<!-- Shiro Security filter filter-name这个名字的值将来还会在spring中用到 -->
<!-- 注意:shiro的filter必须在struts2的filter之前,否则action无法创建 -->
<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>
applicationContext.xml
<!--Shiro安全框架产生代理子类的方式: 使用cglib方式-->
<aop:aspectj-autoproxy proxy-target-class="true" />
ehcache-shiro.xml
<?xml version="1.0" encoding="UTF-8"?>
<ehcache updateCheck="false" name="shiroCache">
<defaultCache
maxElementsInMemory="10000"
eternal="false"
timeToIdleSeconds="120"
timeToLiveSeconds="120"
overflowToDisk="false"
diskPersistent="false"
diskExpiryThreadIntervalSeconds="120"
/>
</ehcache>
applicationContext-shiro.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<description>Shiro配置文件</description>
<!-- SecurityManager配置 -->
<!-- 配置Realm域 -->
<!-- 密码比较器 -->
<!-- 代理如何生成? 用工厂来生成Shiro的相关过滤器-->
<!-- 配置缓存:ehcache缓存 -->
<!-- 安全管理 -->
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
<!-- Single realm app. If you have multiple realms, use the 'realms' property instead. -->
<property name="realm" ref="authRealm"/><!-- 引用自定义的realm -->
<!-- 缓存 -->
<property name="cacheManager" ref="shiroEhcacheManager"/>
</bean>
<!-- 自定义权限认证 -->
<bean id="authRealm" class="cn.itcast.jk.shiro.AuthRealm">
<property name="userService" ref="userService"/>
<!-- 自定义密码加密算法 -->
<property name="credentialsMatcher" ref="passwordMatcher"/>
</bean>
<!-- 设置密码加密策略 md5hash -->
<bean id="passwordMatcher" class="cn.itcast.jk.shiro.CustomCredentialsMatcher"/>
<!-- filter-name这个名字的值来自于web.xml中filter的名字 -->
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
<property name="securityManager" ref="securityManager"/>
<!--登录页面 -->
<property name="loginUrl" value="/index.jsp"></property>
<!-- 登录成功后 -->
<property name="successUrl" value="/home.action"></property>
<property name="filterChainDefinitions">
<!-- /**代表下面的多级目录也过滤 -->
<value>
/index.jsp* = anon
/home* = anon
/sysadmin/login/login.jsp* = anon
/sysadmin/login/logout.jsp* = anon
/login* = anon
/logout* = anon
/components/** = anon
/css/** = anon
/images/** = anon
/js/** = anon
/make/** = anon
/skin/** = anon
/stat/** = anon
/ufiles/** = anon
/validator/** = anon
/resource/** = anon
/** = authc
/*.* = authc
</value>
</property>
</bean>
<!-- 用户授权/认证信息Cache, 采用EhCache 缓存 -->
<bean id="shiroEhcacheManager" class="org.apache.shiro.cache.ehcache.EhCacheManager">
<property name="cacheManagerConfigFile" value="classpath:ehcache-shiro.xml"/>
</bean>
<!-- 保证实现了Shiro内部lifecycle函数的bean执行 -->
<bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/>
<!-- 生成代理,通过代理进行控制 -->
<bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"
depends-on="lifecycleBeanPostProcessor">
<property name="proxyTargetClass" value="true"/>
</bean>
<!-- 安全管理器 -->
<bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">
<property name="securityManager" ref="securityManager"/>
</bean>
</beans>
MD5Hash散列加密及shiro自定义密码比较器
加密工具类
org.apache.shiro.crypto.hash.Md5Hash.Md5Hash(Object source,Object salt, int hashIterations)
public class Encrypt {
/*
* 散列算法一般用于生成数据的摘要信息,是一种不可逆的算法,一般适合存储密码之类的数据,
* 常见的散列算法如MD5、SHA等。一般进行散列时最好提供一个salt(盐),比如加密密码“admin”,
* 产生的散列值是“21232f297a57a5a743894a0e4a801fc3”,
* 可以到一些md5解密网站很容易的通过散列值得到密码“admin”,
* 即如果直接对密码进行散列相对来说破解更容易,此时我们可以加一些只有系统知道的干扰数据,
* 如用户名和ID(即盐);这样散列的对象是“密码+用户名+ID”,这样生成的散列值相对来说更难破解。
*/
//高强度加密算法,不可逆
public static String md5(String password, String salt){
return new Md5Hash(password,salt,2).toString();
}
public static void main(String[] args) {
System.out.println(new Md5Hash("123456","zhangsan"+"cgx",5).toString());
}
}
自定义密码比较器
public class CustomCredentialsMatcher extends SimpleCredentialsMatcher {
//密码比较的方法 token代表用户在界面输入的用户名和密码 info代表从数据库中得到加密数据
public boolean doCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) {
//1.向下转型
UsernamePasswordToken upToken = (UsernamePasswordToken) token;
//2.将用户在界面输入的原始密码加密
Object pwd = Encrypt.md5(new String(upToken.getPassword()), upToken.getUsername());
//3.取出数据库中加密的密码
Object dbPwd = info.getCredentials();
return this.equals(pwd, dbPwd);
}
}
实现shiro登陆校验及授权
登陆方法
public String login() throws Exception {
if(UtilFuns.isEmpty(username)){
return "login";
}
try {
//1.得到Subject
Subject subject = SecurityUtils.getSubject();
//2.调用登录方法
UsernamePasswordToken token = new UsernamePasswordToken(username, password);
subject.login(token);//当这一代码执行时,就会自动跳入到AuthRealm中认证方法
//3.登录成功时,就从Shiro中取出用户的登录信息
User user = (User) subject.getPrincipal();
//4.将用户放入session域中
session.put(SysConstant.CURRENT_USER_INFO, user);
} catch (Exception e) {
e.printStackTrace();
request.put("errorInfo", "对不起,用户名或密码错误!");
return "login";
}
return SUCCESS;
}
Realm自定义安全数据桥(域)
public class AuthRealm extends AuthorizingRealm {
private UserService userService;
public void setUserService(UserService userService) {
this.userService = userService;
}
//授权 当jsp页面出现Shiro标签时,就会执行授权方法
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection pc) {
System.out.println("授权");
User user = (User) pc.fromRealm(this.getName()).iterator().next();//根据realm的名字去找对应的realm
Set<Role > roles = user.getRoles();//对象导航
List<String> permissions = new ArrayList<String>();
for(Role role :roles){
//遍历每个角色
Set<Module> modules = role.getModules();//得到每个角色下的模块列表
for(Module m :modules){
permissions.add(m.getName());
}
}
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
info.addStringPermissions(permissions);//添加用户的模块(权限)
return info;
}
//认证 token 代表用户在界面输入的用户名和密码
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
System.out.println("认证");
//1.向下转型
UsernamePasswordToken upToken = (UsernamePasswordToken) token;
//2.调用业务方法,实现根据用户名查询
String hql = "from User where userName=?";
List<User> list = userService.find(hql, User.class, new String[]{upToken.getUsername()});
if(list!=null && list.size()>0){
User user = list.get(0);
AuthenticationInfo info = new SimpleAuthenticationInfo(user,user.getPassword(),this.getName());
return info; //此处如果返回,就会立即进入到密码比较器
}
return null;//就会出现异常
}
}
shiro标签使用
<!-- 当jsp页面碰到shiro标签时就执行AuthRealm中授权方法 -->
<shiro:hasPermission name="系统首页">
<span id="topmenu" οnclick="toModule('home');">系统首页</span><span id="tm_separator"></span>
</shiro:hasPermission>
<shiro:hasPermission name="货运管理">
<span id="topmenu" οnclick="toModule('cargo');">货运管理</span><span id="tm_separator"></span>
</shiro:hasPermission>
<shiro:hasPermission name="统计分析">
<span id="topmenu" οnclick="toModule('stat');">统计分析</span><span id="tm_separator"></span>
</shiro:hasPermission>
<shiro:hasPermission name="基础信息">
<span id="topmenu" οnclick="toModule('baseinfo');">基础信息</span><span id="tm_separator"></span>
</shiro:hasPermission>
<shiro:hasPermission name="系统管理">
<span id="topmenu" οnclick="toModule('sysadmin');">系统管理</span>
</shiro:hasPermission>
<shiro:hasPermission name="流程管理">
<span id="topmenu" οnclick="toModule('activiti');">流程管理</span>
</shiro:hasPermission>
struts2全局异常处理
1.自定义异常处理类
public class SysException extends Exception {
private String message;
public String getMessage() {
return message;
}
public SysException(String message) {
this.message = message;
}
}
2.在struts.xml中进行全局异常的配置
<!-- 配置全局异常 sysException,error -->
<global-results>
<result name="sysException">/WEB-INF/pages/error.jsp</result>
<result name="error">/WEB-INF/pages/error.jsp</result>
</global-results>
<global-exception-mappings>
<exception-mapping result="sysException" exception="cn.itcast.jk.exceptioin.SysException"/>
<exception-mapping result="error" exception="java.lang.Exception"/>
</global-exception-mappings>
3.pages/error.jsp页面的加入
<%@ page contentType="text/html;charset=UTF-8" isErrorPage="true" %>
<%@taglib prefix="s" uri="/struts-tags"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>Error Page</title>
<script language="javascript">
function showDetail()
{
var elm = document.getElementById('detail_system_error_msg');
if(elm.style.display == '') {
elm.style.display = 'none';
}else {
elm.style.display = '';
}
}
</script>
</head>
<body style="font-family:微软雅黑;">
<div id="content" style="text-align:left;">
<table>
<tr>
<td><img alt="system internal error" src="${pageContext.request.contextPath }/images/error01.jpg"/></td>
<br>
<b>错误信息:</b>
<div style="color:blue;padding:15px;">
<s:property value="exception.message"/>
</div>
<button οnclick="history.back();">返回</button>
<p><a href="#" οnclick="showDetail();">点击这里查看具体错误消息</a>,
<br/>
报告以下错误消息给系统管理员,可以更加快速的解决问题;
<br/>联系电话:120
</p>
</td>
</tr>
</table>
<div id="detail_system_error_msg" style="display:none;text-align:left;padding-bottom:100px;">
<pre><s:property value="exceptionStack"/></pre>
</div>
</div>
</body>
</html>
两个图片加入WebRoot/images目录下