java用户授权中心的实现

简介:文章主要介绍企业多个应用系统的统一认证授权系统的实现,提供完整的用户身份认证以及权限管理,同一用户权限管理,实现所有业务子系统的单点登录登出。


1.采用框架

spring3.1.1 + springmvc + mybatis3.1.1 + shiro1.2.4 + activemq  前端框架:bootstrap

shiro:权限控制框架

activemq:授权中心token分发以及日志消息处理

2.系统主要功能

2.1业务系统:管理需要被授权的子系统(主要包括:系统名称,系统首页地址,系统授权码)

2.2 模块管理:维护系统的功能模块

2.3 菜单管理:维护系统的菜单

2.4 按钮管理:按钮维护(系统权限精确到按钮级)

2.5 用户管理:用户信息维护

2.6 角色管理:角色维护

主要表结构如下:

授权主要流程图如下:


3.授权中心登录实现

系统的权限管理采用shiro框架控制(shiro教程:http://jinnianshilongnian.iteye.com/blog/2018398)

登录及token分发主要代码:

@RequestMapping("/login")
public String login(String account,String password,ModelMap model,HttpServletRequest request,HttpServletResponse response){
log.info("用户登录*******************");

Subject subject = SecurityUtils.getSubject();
UsernamePasswordToken token = new UsernamePasswordToken(account,MD5Encrypt.Md5(password));
token.setRememberMe(false);
try {
subject.login(token);
//登录成功后获取重定向地址 该地址为业务系统传递的登录成功后跳转返回地址
Object obj = request.getSession().getAttribute("redictUrl");
String url = obj == null ? null : obj.toString();
if(url != null && url.length() > 0){
//当重定向地址不为空时  重定向到当前URL且带上token
url += "?token=" + request.getSession().getAttribute("token") + "&";
request.getSession().setAttribute("redictUrl",null);
return "redirect:" + url;
}
//重定向地址为空时  跳转到授权中心主页
            return "redirect:page/main.jsp";
        }catch (AuthenticationException ex) {
        log.info(("登录失败错误信息:"+ex.getMessage()));
            ex.printStackTrace();
            token.clear();
            //设置错误信息  跳转到登录页面 
            model.addAttribute("errorMsg",ex.getMessage());
            return "login/login";
        }

}


/**
* 认证信息 通过比对数据库要比对用户和密码
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(
AuthenticationToken paramAuthenticationToken)
throws AuthenticationException {
UsernamePasswordToken token = (UsernamePasswordToken) paramAuthenticationToken;
String userName = token.getUsername();
if (userName != null && !"".equals(userName)) {
// 用户登录
SystemUserVo user = systemUserService.userLogin(userName,
new String(token.getPassword()));
if (user == null) {
log.info("用户名【{}】或密码【{}】错误", userName, new String(token.getPassword()));
throw new AuthenticationException("用户名或密码错误");
}
//用户状态为空或者为0时表示该帐号被禁用
if (user.getStatus() == null || user.getStatus() == 0) {
log.info("用户名【{}】被禁用,登录失败", userName);
throw new AuthenticationException("该帐号已被禁用");
}
// 用户登录成功后 生成token并下发业务系统
JSONObject tokenJson = getTokenJson(user);
// 将token放入缓存中
CacheUtils.addCache(tokenJson.get("token"), tokenJson);
//将用户信息放入session中
SecurityUtils.getSubject().getSession().setAttribute("currentUser",JSONObject.fromObject(tokenJson.get("userInfo")));
//将token放入session中
SecurityUtils.getSubject().getSession().setAttribute("token", tokenJson.get("token"));
//将token信息放入session中
SecurityUtils.getSubject().getSession().setAttribute("tokenJson", tokenJson);
// MQ下发token
(主题订阅方式)  MQUtils.getQueueName("mqTokenTopic")获取token订阅的主题
TopicServer.getSingleInstance().publishMessageThread(MQUtils.getQueueName("mqTokenTopic"), tokenJson.toString());
// 清除当前用户之前登录的token 用于禁止一个帐号多次登录
String removeToken = CacheUtils.clearToken(tokenJson);
// MQ清除token
Map<String, String> map = new HashMap<>();
map.put("type", "delete");
map.put("token", removeToken);
//告知子系统当前tonken已被删除
TopicServer.getSingleInstance().publishMessageThread(
MQUtils.getQueueName("mqTokenTopic"), JSONObject.fromObject(map).toString());
// token生成和下发完成
return new SimpleAuthenticationInfo(user.getAccount(), user
.getPassword().toCharArray(), getName());
} else {
log.info("用户名为空");
}
return null;
}

生成token(包含用户权限信息,此处可优化为只下发token,业务系统利用用户登录token和系统授权token获取用户本系统的角色及菜单权限)

/**

* @Description: TODO 根据当前登录用户 生成token
* @param @param user 当前登录用户
* @param @return
* @return JSONObject token及授权信息的json字符串
* @throws
* @author 邱林
* @date 2015年11月2日 下午3:00:33
*/
private JSONObject getTokenJson(SystemUserVo user) {
Map<String, Object> tokenMap = new HashMap<>();
Long userId = user.getId();
// 生成token并和客户端绑定
tokenMap.put("type", "add");// 设置tokne的类型为新加token
tokenMap.put("times", 0);//设置token被激活的次数为0
String token = TokenUtils.getToken();//获取token
tokenMap.put("token", token);//设置token
tokenMap.put("clientIp", SecurityUtils.getSubject().getSession()
.getHost());//设置当前token生成时的IP
tokenMap.put("userInfo", user);// 设置用户信息
tokenMap.put("role", systemPressService.getUserRole(userId));// 设置用户角色
List<Map<String, Object>> systemList = systemPressService
.getUserSystem(userId);
tokenMap.put("system", systemList);// 设置用户拥有的系统权限
tokenMap.put("module",
systemPressService.getUserModule(systemList, userId, token));// 获取用户拥有的菜单权限
tokenMap.put("button",
systemPressService.getUserButton(systemList, userId));// 获取用户拥有的按钮权限
JSONObject json = JSONObject.fromObject(tokenMap);
return json;
}

4.业务系统从授权中心获取用户授权

业务系统在系统启动时订阅tokenTopic 用于接收授权中心分发的token,代码如下:

//订阅token主题   TokenSubMessageHandler订阅消息的消息处理类
TopicClient tc = new TopicClient(new TokenSubMessageHandler());
try {
//MQUtils.getTokenTopic() 获取token订阅的主题
tc.subTopic(MQUtils.getTokenTopic());
} catch (JMSException e) {
e.printStackTrace();
}

业务系统shiro登录地址配置:(http://qiulinq.eicp.net:801为授权中心地址,redictUrl=http://qiulinq.eicp.net:802/log为登录成功后跳转到对应业务系统的链接

<property name="loginUrl" value="http://qiulinq.eicp.net:801/logout?redictUrl=http://qiulinq.eicp.net:802/log" />

授权中心http://qiulinq.eicp.net:801/logout实现如下:

@RequestMapping("/logout")
public String logout(HttpServletRequest request){
//调用shiro的登出方法
        SecurityUtils.getSubject().logout();
        //获取重定向地址
        String redictUrl = request.getParameter("redictUrl");
        if(redictUrl != null && redictUrl.length() > 0){
        //当重定向地址不为空时  放到session中
        request.getSession().setAttribute("redictUrl", redictUrl);
        }
        //获取当前session中的token
        Object token = request.getSession().getAttribute("token");
        if(token != null){
        Map<String, Object> map = new HashMap<String, Object>();
            map.put("type", "delete");
    map.put("token", token);
    //告知业务端token失效
    TopicServer.getSingleInstance().publishMessageThread(MQUtils.getQueueName("mqTokenTopic"), JSONObject.fromObject(map).toString());
        }
        
return "login/login";
}

授权中心登录成功后会携带token跳转回到当前业务子系统。

5.子系统过滤及token验证

在shiro的配置文件中新增单点登录的过滤器:

<!-- 自定义的单点登录过滤器 -->
<bean id="ssoFilter" class="com.shuilin.support.filter.SSOFilter"></bean> 

shiro主要过滤配置:<!-- shiro的主过滤器,beanId 和web.xml中配置的filter name需要保持一致 -->
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
<property name="securityManager" ref="securityManager" />
<!-- 未登录的跳转页面  重定向到授权中心 -->
<property name="loginUrl" value="http://qiulinq.eicp.net:801/logout?redictUrl=http://qiulinq.eicp.net:802/log" />
<property name="unauthorizedUrl" value="/page/login.jsp" />
<property name="filters">    
           <map>    
            <!-- 定义shiro的过滤器 -->
               <entry key="sso" value-ref="ssoFilter"/>  
         </map>    
       </property>
<property name="filterChainDefinitions">
<value>
<!-- 当前系统下面的所有资源由单点登录的过滤器保护 -->
/** = sso
</value>
</property>
</bean>

SSOFilter代码如下:

package com.shuilin.support.filter;


import java.util.UUID;


import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;


import net.sf.json.JSONObject;


import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.web.filter.authz.AuthorizationFilter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


import com.shuilin.support.cache.CacheUtils;
import com.shuilin.support.utils.MD5Encrypt;
/**
 * 
 * ClassName: SSOFilter 单点登录过滤器  继承shiro的认证过滤器
 * @Description: TODO
 * @author 邱林
 * @date 2015年11月3日 上午9:20:20
 */
public class SSOFilter extends AuthorizationFilter{



private static Logger log = LoggerFactory.getLogger(SSOFilter.class);
@Override
protected boolean isAccessAllowed(ServletRequest request,
ServletResponse response, Object obj) throws Exception {

HttpServletRequest req = (HttpServletRequest) request;
String token = req.getParameter("token");
//判断当前session中是否存在用户
out : if(req.getSession().getAttribute("currentUser") != null){
//存在用户 则取当前session中的tokenJson对象
JSONObject tokenJson = (JSONObject) req.getSession().getAttribute("tokenJson");
if(tokenJson != null){
//当tokenJson不为null时  判断当前token是否在token缓存中存在  判断该token还有效
if(CacheUtils.getCache(tokenJson.getString("token")) == null){
log.info("token失效,强制用户退出..............");
//当token缓存中取到的值为空时说名当前token已被移除缓存  token已失效
SecurityUtils.getSubject().logout();
//判断当前请求(request)中是否包含token 不包含则直接return false表示验证失败
if(token == null){
return false;
}else{
//包含token则跳出out循环 继续验证当前request的token是否有效
break out;
}
}
}
return true;
}
//当token不为null时做登录验证
if(token != null && token.length() > 0){
try{
//获取shiro的主体
Subject subject = SecurityUtils.getSubject();
//创建shiro的token token作为用户名  密码为随机的uuid(此处只对token做验证 密码无实际意义)
UsernamePasswordToken subToken = new UsernamePasswordToken(token,MD5Encrypt.Md5(UUID.randomUUID().toString()));
//shiro做登录
subject.login(subToken);
//登录成功时返回true
return true;
}catch(Exception e){
e.printStackTrace();
return false;
}
}
log.info("用户未登录,且不存在token或者token错误,重定向到授权中心登录,token:{}",token);
return false;
}
}

客户端系统的token验证以及获取用户权限代码:

package com.shuilin.support.filter;


import java.util.HashMap;
import java.util.Map;


import net.sf.json.JSONObject;


import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.Subject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


import com.shuilin.support.cache.CacheUtils;
import com.shuilin.support.mq.client.MessageSender;
import com.shuilin.support.mq.util.MQUtils;
import com.shuilin.support.utils.HttpClientUtil;
import com.shuilin.support.utils.PropertiesUtils;
import com.shuilin.support.utils.SessionUtils;


public class ShiroRealm extends AuthorizingRealm{
private static Logger log = LoggerFactory.getLogger(ShiroRealm.class);

/** 
     * 授权信息 
     */ 
@Override
protected AuthorizationInfo doGetAuthorizationInfo(
PrincipalCollection paramPrincipalCollection) {
       return SessionUtils.getUserPress();
}
/** 
     * 认证信息
     */
@Override
protected AuthenticationInfo doGetAuthenticationInfo(
AuthenticationToken paramAuthenticationToken)
throws AuthenticationException {
//用户token
UsernamePasswordToken userToken = (UsernamePasswordToken) paramAuthenticationToken;
//获取到授权中心下发的token
String token = userToken.getUsername();
Subject subject =  SecurityUtils.getSubject();
//校验token
if(checkToken(token, subject.getSession().getHost())){
return new SimpleAuthenticationInfo(token, userToken.getPassword(), getName());
}
return null;
}

private static boolean checkToken(String token,String clientIp){
if(token == null){
log.info("单点登录时获取到的token为空,直接返回false【单点登录失败】");
return false;
}
log.info("单点登录时获取到的token为:{}",token);
//取得缓存中的token
JSONObject tokenJson = (JSONObject) CacheUtils.getCache(token);
if(tokenJson == null){
log.info("单点登录时缓存中获取token信息为空,token为:{}",token);
String url = PropertiesUtils.readProperties("authriazeUrl", "com/shuilin/config/properties/server");
url += "checkToken?token=" + token;
log.info("通过HTTP请求实时校验token:{}",url);
String res = HttpClientUtil.sendGetRequest(url, "UTF-8");
log.info("HTTP请求校验token返回的结果为:{}",res);
//当http请求的结果为空时 说明当前token无效  直接返回
if(res == null || res.length() == 0){
return false;
}
tokenJson = JSONObject.fromObject(res);
//将http请求到的token信息放入到缓存中  防止filter校验时取不到
CacheUtils.addCache(tokenJson.get("token"), tokenJson);
}
log.info("单点登录时获取到的token信息为:{}" ,tokenJson);
//判断当前用户的IP与token绑定的IP是否一致
if(!clientIp.equals(tokenJson.getString("clientIp"))){
log.info("当前绑定的IP与token的IP不一致");
return false;
}
//MQ告知授权中心该系统激活了token
Map<String, Object> map = new HashMap<String, Object>();
map.put("token", token);
//inuse表示当前token被使用
map.put("type", "inUse");
//MQ发送消息 告知授权中心当前token被激活了一次 用户实现单点登录
MessageSender.getSingleInstance().sendMessageThread(JSONObject.fromObject(map).toString(), MQUtils.getQueueName("mqTokenServerQueue"));
//在tokenJson中获取到用户信息 并放入session中
Map<String, Object> userMap = JSONObject.fromObject(tokenJson.getJSONObject("userInfo"));
SecurityUtils.getSubject().getSession().setAttribute("currentUser", userMap);
//将当前token信息放入到session中
SecurityUtils.getSubject().getSession().setAttribute("tokenJson", tokenJson);
//return true表示当前的token通过校验
return true;
}
}


子系统根据系统token获取用户当前系统的菜单权限:

/**

* @Description: TODO获取用户的菜单权限
* @param @return   
* @return Map<String,Object>  
* @throws
* @author 邱林
* @date 2015年11月6日 上午10:20:39
*/
@RequestMapping("/menu")
@ResponseBody
public Map<String, Object> indexMenu(){
//获取当前用户的授权信息
JSONObject json = (JSONObject) SecurityUtils.getSubject().getSession().getAttribute("tokenJson");
Map<String, Object> map = new HashMap<String, Object>();
//根据当前的系统授权码获取用户的菜单权限
String serverToken = PropertiesUtils.readProperties("serverToken", "com/shuilin/config/properties/server");
if(!json.getJSONObject("module").has(serverToken)){
log.info("无任何菜单的授权");
return null;
}
map.put("menu", json.getJSONObject("module").getString(serverToken));
return map;
}


AOP日志管理以及权限权限控制:

package com.shuilin.support.aop;


import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;


import javax.annotation.Resource;


import net.sf.json.JSONArray;
import net.sf.json.JSONObject;


import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authz.UnauthenticatedException;
import org.apache.shiro.subject.Subject;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RequestMapping;


import com.shuilin.support.bean.SystemOptLog;
import com.shuilin.support.dao.CommonDao;
import com.shuilin.support.mq.client.MessageSender;
import com.shuilin.support.mq.util.MQUtils;
import com.shuilin.support.utils.DateUtils;
import com.shuilin.support.utils.JsonUtils;
import com.shuilin.support.utils.SessionUtils;


@Component
@Aspect
public class AopLogUtils {
@Resource
private CommonDao commonDao;


// 处理并发日志
static ThreadLocal<List<SystemOptLog>> map0 = new ThreadLocal<List<SystemOptLog>>() {
@Override
protected List<SystemOptLog> initialValue() {
return new ArrayList<SystemOptLog>();
}
};
// log4j日志类
private static Logger log = LoggerFactory.getLogger(AopLogUtils.class);


// 定义service层log切入点
@Pointcut("execution(* com..service.impl..*.*(..))")
public void serviceLogPointCut() {}


// 定义dao层log切入点
@Pointcut("execution(* com..dao.impl..*.*(..))")
public void daoLogPointCut() {}


// controller的切面 用户强制验证按钮权限 com..controller
@Pointcut("within(@org.springframework.stereotype.Controller *)")
public void cutController() {}


// 发生异常的AOP拦截
public void doThrowing(JoinPoint jp, Throwable ex) {
ex.printStackTrace();
}


// dao层操作前日志
@Before("daoLogPointCut()")
public void doDaoLogBefore(JoinPoint joinPoint) {
String daoMethod = joinPoint.getSignature().getName();
// 只对增删改做日志记录
if ((daoMethod.startsWith("save") || daoMethod.startsWith("add")
|| daoMethod.startsWith("update") || daoMethod
.startsWith("del"))) {
List<SystemOptLog> list = map0.get();
if (list.size() > 0) {
SystemOptLog systemLog = new SystemOptLog();
BeanUtils.copyProperties(list.get(0), systemLog);
systemLog.setDaoClass(joinPoint.getTarget().getClass()
.toString());// 设置dao的类
systemLog.setDaoMethod(joinPoint.getSignature().getName());// 设置dao的方法
systemLog.setDaoParams(JSONArray
.fromObject(joinPoint.getArgs()).toString());// 设置dao的参数
Object obj = null;
Object params = joinPoint.getArgs()[0];
Class paramsClass = params.getClass();
if (!systemLog.getDaoMethod().startsWith("del")) {// 判断是否是删除
systemLog.setNewData(JSONArray.fromObject(
joinPoint.getArgs()).toString());// 设置数据操作后的值
try {
// 删除
obj = paramsClass.getDeclaredMethod("getId").invoke(
params);
} catch (Exception e) {
e.printStackTrace();
}
} else {
obj = joinPoint.getArgs()[0];
}
if (obj != null) {
String sql = "select * from "
+ changeToTableName(joinPoint.getTarget()
.getClass().toString()) + " where id = "
+ obj;
List<Map<String, Object>> ls = commonDao.queryBySql(sql);
systemLog.setOldData(JSONArray.fromObject(ls,JsonUtils.getJsonConfig()).toString());// 设置操作的数据的原始值
}
list.add(systemLog);
}
}
}


// service层执行时的
@Around("serviceLogPointCut()")
public Object doServiceAround(ProceedingJoinPoint joinPoint)
throws Throwable {
List<SystemOptLog> list = map0.get();
String serviceMethod = joinPoint.getSignature().getName();// service的方法
String serviceClass = joinPoint.getTarget().getClass().toString();// service的类
// 只对增删改做日志记录
if ((serviceMethod.startsWith("save")
|| serviceMethod.startsWith("add")
|| serviceMethod.startsWith("update") || serviceMethod
.startsWith("del"))
&& serviceClass.indexOf("SystemOptLog") < 0) {
SystemOptLog systemLog = new SystemOptLog();
systemLog.setServiceMethod(joinPoint.getSignature().getName());// service的方法
systemLog.setOptId(UUID.randomUUID().toString());// 操作ID
// 同一个事物的操作ID保持一致
systemLog.setServiceClass(joinPoint.getTarget().getClass()
.toString());// service的类
systemLog.setServiceParams(JSONArray
.fromObject(joinPoint.getArgs()).toString());// service的参数
systemLog.setOptTime(DateUtils.nowDate2String());// 设置操作时间
systemLog.setOptUserid(SessionUtils.getUserId());// 设置当前用户的ID
systemLog.setOptUsername(SessionUtils.getRealName());// 设置当前用户的姓名
list.add(systemLog);
}
Object o = joinPoint.proceed();
// 当当前list的size大于0 表示存在事务 需要记录日志
if (list.size() > 0) {
list.remove(0);
for (SystemOptLog systemLog : list) {
systemLog.setResult(JSONObject.fromObject(o).toString());
}
// MQ发送到日志系统 mqLogQueue需要配置日志的queue
MessageSender.getSingleInstance().sendMessageThread(
JSONArray.fromObject(list).toString(),
MQUtils.getQueueName("mqLogQueue"));
}
// 删除当前日志
map0.remove();
return o;
}


// service返回后执行
@AfterReturning(pointcut = "serviceLogPointCut()", returning = "result")
public void doServiceAfter(Object result) {
// log.info("返回的结果为:{}",result );
}


/**

* @Description: TODO强制权限拦截
* @param @param jp
* @param @throws Throwable
* @return void
* @throws
* @author 邱林
* @date 2015年11月6日 上午10:29:52
*/
@Before("cutController()")
public void recordSysLog(JoinPoint jp) throws Throwable {
// 获取访问controller的类
Class clz = jp.getTarget().getClass();
// 获取类的requestMapping注解
RequestMapping classMapping = (RequestMapping) clz
.getAnnotation(RequestMapping.class);
// 方法的requestMapping注解
RequestMapping methodMapping = null;
for (Method m : clz.getDeclaredMethods()) {
if (m.getName().equals(jp.getSignature().getName())) {
methodMapping = m.getAnnotation(RequestMapping.class);
}
}
// 将类的请求地址和方法的请求地址拼装成权限地址 格式 classReqUrl:methodReqUrl
StringBuffer sb = new StringBuffer();
if (classMapping != null) {
sb.append(classMapping.value()[0].replace("/", "") + ":");
}
if (methodMapping != null) {
sb.append(methodMapping.value()[0].replace("/", ""));
}
Subject subject = SecurityUtils.getSubject();
// 判断用户是否有此权限 admin角色拥有所有权限
if (!map.containsKey(sb.toString())) {
if (!(subject.isPermitted(sb.toString()) || subject
.hasRole("admin"))) {
log.info("用户【{}】权限异常,权限代码为:【{}】", SessionUtils.getRealName()
+ "  " + SessionUtils.getUserAccount(), sb.toString()
.replace("/", ""));
// 抛出权限异常
throw new UnauthenticatedException("您无此操作权限,如需继续操作,请联系管理员。权限代码:["
+ sb.toString().replace("/", "") + "]");
}
}
}


// 设置权限拦截的白名单 static只初始化一次
private static Map<String, Object> map = new HashMap<String, Object>();
static {
map.put("login", "");// 登录不需要强制权限拦截
map.put("index", "");// 跳转到首页不需要强制权限拦截
map.put("menu", "");// 菜单
map.put("checkToken", "");// 校验token
map.put("logout", "");// 登出
map.put("systemList", "");// 系统列表
map.put("dict:getAll", "");//数据字典设置权限不拦截
}


/**

* @Description: TODO将dao类名转换成表名
* @param @param className dao类名
* @param @return
* @return String 对应的表名
* @throws
* @author 邱林
* @date 2015年11月6日 上午10:24:10
*/
private static String changeToTableName(String className) {
if (className.indexOf(".") >= 0) {
className = className.substring(className.lastIndexOf(".") + 1,
className.length());
}
char[] chars = className.toCharArray();
StringBuffer sb = new StringBuffer();
for (char c : chars) {
if (c >= 'A' && c <= 'Z' && sb.length() > 0) {
sb.append("_");
}
sb.append(c);
}
return sb.toString().toLowerCase().replace("_dao_impl", "");
}
}


系统源码会在整理后贴出

  • 2
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值