您的位置:首页 > 编程语言 > Java开发

简单权限系统基于shiro-springmvc-spring-mybatis(学习笔记2)

2016-10-13 14:36 651 查看
学习笔记(1)链接:http://blog.csdn.net/qq_15370821/article/details/52798276

一个简单的权限管理系统,实现用户、权限、资源的增删改查,这三者之间相互的授权和取消授权,如:一个用户可以拥有多个权限并且一个权限可以拥有多个资源。

系统基于shiro、springmvc、spring、mybatis,使用MySQL数据库。

项目地址:https://git.oschina.net/beyondzl/spring-shiro

(前端视图由于时间原因没有全部完成,后端功能测试可行)

Web层

springmvc.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:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.1.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.1.xsd"> 
<mvc:annotation-driven >
<mvc:message-converters register-defaults="false">
<bean class="org.springframework.http.converter.StringHttpMessageConverter">
<constructor-arg value="utf-8"></constructor-arg>
</bean>
<ref bean="jacksonMessageConverter"></ref>
</mvc:message-converters>
</mvc:annotation-driven>

<bean id="jacksonMessageConverter" class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
<property name="supportedMediaTypes">
<list>
<value>text/html;charset=UTF-8</value>
<value>application/json;charset=UTF-8</value>
</list>
</property>
<property name="objectMapper" ref="jacksonObjectMapper"></property>
</bean>

<context:component-scan base-package="com.spring.shiro.main.java.controller"></context:component-scan>

<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/views/"></property>
<property name="suffix" value=".jsp"></property>
<!-- 有多个视图解析器时的优先级 -->
<property name="order" value="10"></property>
</bean>
</beans>


基础Controller类:

public abstract class BaseController {

@Autowired
private UserService userService ;

/**
* 日期格式转换
* @param binder
*/
@InitBinder
public void initBinder(ServletRequestDataBinder binder) {
binder.registerCustomEditor(Date.class, new CustomDateEditor(new SimpleDateFormat("yyyy-MM-dd"),true));

/**
* 防止XSS攻击
*/
binder.registerCustomEditor(String.class, new StringEscapeEditor(true,false));
}

/**
* 获取当前登录用户
* @return
*/
public User getCurrentUser() {
ShiroUser user = (ShiroUser) SecurityUtils.getSubject().getPrincipal();
User currentUser = userService.findUserById(user.id);
return currentUser;
}

/*
* 获取当前用户id
*/
public Long getUserUd() {
return this.getCurrentUser().getId();
}

/**
* 获取当前用户名
* @return
*/
public String getStaffName() {
return this.getCurrentUser().getName();
}

/**
* ajax失败
* @param msg 失败的消息
* @return
*/
public Object renderError(String msg) {
Result result = new Result();
result.setMsg(msg);
return result;

}

/**
* ajax成功
* @return
*/
public Object renderSuccess() {
Result result = new Result();
result.setSuccess(true);
return result;
}

/**
* ajax成功消息
* @param msg
* @return
*/
public Object renderSuccess(String msg) {
Result result = new Result();
result.setSuccess(true);
result.setMsg(msg);
return result;
}

/**
* ajax成功时的对象
* @param obj
* @return
*/
public Object renderSuccess(Object obj) {
Result result = new Result();
result.setSuccess(true);
result.setObj(obj);
return result;
}
}


handler继承基本Controller类:

@Controller
@RequestMapping("/user")
public class UserController extends BaseController {
@Autowired
private UserService userService;

/**
* 用户管理页
* @return
*/
@RequestMapping(value="/manager",method=RequestMethod.GET)
public String manager() {
return "/admin/user";
}

/**
* 用户管理列表
* @param userVo
* @param page
* @param rows
* @param sort
* @return
*/
@RequestMapping(value="/dataGrid", method=RequestMethod.POST)
@ResponseBody
public Object dataGrid(UserVo userVo, Integer page, Integer rows, String sort) {
PageInfo pageInfo = new PageInfo(page, rows);
Map<String, Object> condition = new HashMap<String, Object>();

if(StringUtils.hasText(userVo.getName())) {
condition.put("name", userVo.getName());
}
if(userVo.getOrganizationId() != null) {
condition.put("organizationId", userVo.getOrganizationId());
}
if(userVo.getCreatedateStart() != null) {
condition.put("startTime", userVo.getCreatedateStart());
}
if(userVo.getCreatedateEnd() != null) {
condition.put("endTime", userVo.getCreatedateEnd());
}
pageInfo.setCondition(condition);
userService.findUserGrid(pageInfo);
return pageInfo;

}

/**
* 添加用户页
* @return
*/
@RequestMapping(value="addPage", method=RequestMethod.GET)
public String addPage() {
return "/admin/userAdd";
}

/**
* 添加用户
* @param userVo
* @return
*/
@RequestMapping(value="/add",method=RequestMethod.POST)
@ResponseBody
public Object add(UserVo userVo)  {
User user = userService.findUserByLoginName(userVo.getLoginName());
if(user != null) {
return renderError("用户名已存在!");
}
try {
userVo.setPassword(DigestUtils.md5Hex(userVo.getPassword().getBytes("UTF-8")));
} catch (UnsupportedEncodingException e) {
return renderSuccess("添加失败!");
}
userService.addUser(userVo);
return renderSuccess("添加成功!");
}

/**
* 编辑用户页
* @param id
* @param model
* @return
*/
@RequestMapping("/editPage")
public String editPage(Long id,Model model) {
UserVo userVo = userService.findUserVoById(id);
List<Role> rolesList = userVo.getRolesList();
List<Long> idsList = new ArrayList<Long>();
for(Role role : rolesList) {
idsList.add(role.getId());
}
model.addAttribute("roleIds", rolesList);
model.addAttribute("user", userVo);
return "/admin/userEdit";
}

@RequestMapping("/edit")
@ResponseBody
public Object edit(UserVo userVo) {
User user = userService.findUserByLoginName(userVo.getLoginName());
if(user != null && user.getId() != userVo.getId()) {
return renderError("用户名已存在!");
}
try {
userVo.setPassword(DigestUtils.md5Hex(userVo.getPassword().getBytes("UTF-8")));
} catch (UnsupportedEncodingException e) {
return renderError("添加失败!");

}

userService.addUser(userVo);
return renderSuccess("添加成功!");
}

/**
* 修改密码页
* @return
*/
@RequestMapping(value="/editPwdPage", method=RequestMethod.GET)
public String editPwdPage() {
return "/admin/userEditPwd";
}

@RequestMapping("/editUserPwd")
@ResponseBody
public Object editUserPwd(String oldPwd, String pwd) {
try {
if(!getCurrentUser().getPassword().equals(DigestUtils.md5Hex(oldPwd.getBytes("UTF-8")))) {
return renderError("旧密码错误!");
}
} catch (UnsupportedEncodingException e) {
return renderError("修改失败!");
}
userService.updateUserPwdById(getUserUd(), pwd);
return renderSuccess("修改成功!");

}

@RequestMapping("/delete")
@ResponseBody
public Object delete(Long id) {
userService.deleteUserById(id);
return renderSuccess("删除成功!");
}
}


spirng整合shiro

spring-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"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> 
<description>shiro安全配置</description>

<!-- 安全管理器 -->
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager" >
<!-- 设置自定义realm -->
<property name="realm" ref="shiroDbRealm"></property>
<!-- 将缓存管理器交给安全管理器 -->
<property name="cacheManager" ref="shiroEhcacheManager"></property>
</bean>

<!-- 自定义realm -->
<bean id="shiroDbRealm" class="com.spring.shiro.main.common.shiro.ShiroDbRealm"></bean>

<!-- shiro Filter -->
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
<!-- 安全管理器 -->
<property name="securityManager" ref="securityManager"></property>
<!-- 默认的登陆访问url -->
<property name="loginUrl" value="/login"></property>
<!-- 登陆成功后跳转的url -->
<property name="successUrl" value="/index"></property>
<!-- 没有权限跳转的url -->
<property name="unauthorizedUrl" value="/unauth"></property>
<property name="filterChainDefinitions">
<value>
/commons/** = anon <!-- 不需要认证 -->
/static/** = anon
/login = anon
/** = authc <!-- 需要认证 -->
</value>
</property>
</bean>

<!-- 用户授权信息cache 才用Ehcache -->
<bean id="ShiroEhcacheManager" class="org.apache.shiro.cache.ehcache.EhCacheManager">
<property name="cacheManagerConfigFile" value="classpath:ehcache-shiro.xml"></property>
</bean>

<!-- 在方法中注入securityManager进行代理控制 -->
<bean class="org.springframework.beans.factory.config.MethodInvokingBean">
<property name="staticMethod" value="org.apache.shiro.SecurityUtils.setSecurityManager"></property>
<property name="arguments" ref="securityManager"></property>
</bean>

<bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"></bean>

<!-- AOP方法级权限检查 -->
<bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator" depends-on="lifecycleBeanPostProcessor"></bean>

<!-- 启用shiro授权注解拦截方式 -->
<bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">
<property name="securityManager" ref="securityManager"></property>
</bean>
</beans>


ehcache配置

ehcache-shiro.xml:

<?xml version="1.0" encoding="UTF-8"?>
<ehcache updateCheck="false" name="shiroCache">
<defaultCache
maxElementsInMemory="10000"
eternal="false"
timeToIdleSeconds="120"
overToLiveSeconds="120"
overflowToDisk="false"
diskPersistent="false"
diskExpiryThreadIntervalSeconds="120"
/>
</ehcache>


shiro权限认证类:

public class ShiroDbRealm extends AuthorizingRealm {

private static Logger LOGGER = LogManager.getLogger(ShiroDbRealm.class);
@Autowired
private UserService userService;
@Autowired
private RoleService roleService;

/**
* 权限认证
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principal) {

ShiroUser shiroUser = (ShiroUser)principal.getPrimaryPrincipal();
List<Long> roleList = shiroUser.roleList;

Set<String> urlSet = new HashSet<String>();
for(Long roleId : roleList) {
List<Map<Long, String>> roleResourceList = roleService.findRoleResourceListByRoleId(roleId);
if(roleResourceList != null) {
for(Map<Long,String> map : roleResourceList) {
if(StringUtils.hasText(map.get("url"))) {
urlSet.add(map.get("url"));
}
}
}
}
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
info.addStringPermissions(urlSet);
return info;
}

/**
* shiro登陆认证 用户提交用户名密码,shiro封装令牌,realm通过用户名密码查询返回,shiro自动比较用户名密码是否匹配哦,进行登陆控制
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(
AuthenticationToken authcToken) throws AuthenticationException {
LOGGER.info("Shiro开始登陆认证");
UsernamePasswordToken token = (UsernamePasswordToken) authcToken;
User user = userService.findUserByLoginName(token.getUsername());

if(user == null) {
return null;
}
//账号未启用
if(user.getStatus() == 1) {
return null;
}

List<Long> roleList = roleService.findRoleIdsByUserId(user.getId());
ShiroUser shiroUser = new ShiroUser(user.getId(), user.getLoginName(), user.getName(),roleList);
//认证缓存器
return new SimpleAuthenticationInfo(shiroUser, user.getPassword().toCharArray(), getName());

}

}


字符串处理工具类:

public class StringEscapeEditor extends PropertyEditorSupport{
private boolean escaoeHTML; //编码HTML
private boolean escapeJavaScript; //编码javascript

public StringEscapeEditor(){}

public StringEscapeEditor(boolean escapeHTML, boolean escapeJavaScipt){
this.escaoeHTML = escapeHTML;
this.escapeJavaScript = escapeJavaScipt;
}

@Override
public String getAsText() {
Object value = getValue();
return value != null ? value.toString() : "";
}

@Override
public void setAsText(String text) {
if(text == null) {
setValue(null);
}
else {
String value = text;
if(escaoeHTML) {
value = HtmlUtils.htmlEscape(value);
}
if(escapeJavaScript) {
value = JavaScriptUtils.javaScriptEscape(value);
}
setValue(value);
}
}
}


web.xml:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" version="3.0">
<display-name>spring-shiro</display-name>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>
<!-- springmvc控制器 -->
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet.class</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springmvc.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
<!-- 是否支持异步 -->
<async-supported>true</async-supported>
</servlet>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>

<filter>
<filter-name>DruidWebStatFilter</filter-name>
<filter-class>com.alibaba.druid.support.http.WebStatFilter</filter-class>
<init-param>
<param-name>exclusions</param-name>
<param-value>/static/*,*.js,*.gif,*.png,*.css,*.ico,/druid/*</param-value>
</init-param>
<init-param>
<param-name>sessionStatEnable</param-name>
<param-value>false</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>DruidWebStatFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

<!-- shiro过滤 -->
<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>
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
</filter-mapping>

<!-- 错误页面 -->
<error-page>
<error-code>404</error-code>
<location>/WEB-INF/views/error/404.jsp</location>
</error-page>
<error-page>
<error-code>500</error-code>
<location>/WEB-INF/views/error/500.jsp</location>
</error-page>
</web-app>
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
相关文章推荐