shiro 之权限验证问题
2017-10-12 11:54
459 查看
1 shiro的配置,通过maven加入shiro相关jar包
[html] viewplain copy
<!-- shiro -->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-core</artifactId>
<version>1.2.1</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-web</artifactId>
<version>1.2.1</version&
24000
gt;
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-ehcache</artifactId>
<version>1.2.1</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.2.1</version>
</dependency>
2 在web.xml中添加shiro过滤器
[html] viewplain copy
<?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/j2ee" xmlns:javaee="http://java.sun.com/xml/ns/javaee"
xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
id="WebApp_ID" version="2.4">
<!-- 配置spring容器监听器 -->
<span style="color:#ff6666;"> <context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:application-context-*.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener></span>
<!-- post乱码处理 -->
<filter>
<filter-name>CharacterEncodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>utf-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CharacterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- 配置shiro的核心拦截器 -->
<span style="white-space:pre"> </span><filter>
<filter-name>shiroFilter</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>shiroFilter</filter-name>
<url-pattern>/admin/*</url-pattern>
</filter-mapping>
<!-- 配置后台Springmvc 它拦截.do结尾的请求 -->
<servlet>
<servlet-name>back</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springmvc.xml</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>back</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
<display-name>Archetype Created Web Application</display-name>
</web-app>
3 spring中对shiro配置
[html] viewplain copy
<?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:context="http://www.springframework.org/schema/context" xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd"
default-lazy-init="true">
<description>Shiro Configuration</description>
<!-- 加载配置属性文件 -->
<context:property-placeholder ignore-unresolvable="true" location="classpath:jeesite.properties" />
<!-- Shiro权限过滤过滤器定义 -->
<bean name="shiroFilterChainDefinitions" class="java.lang.String">
<constructor-arg>
<value>
/static/** = anon
/userfiles/** = anon
${adminPath}/cas = cas
${adminPath}/login = authc
${adminPath}/logout = logout
${adminPath}/** = user
/act/rest/service/editor/** = perms[act:model:edit]
/act/rest/service/model/** = perms[act:model:edit]
/act/rest/service/** = user
/ReportServer/** = user
</value>
</constructor-arg>
</bean>
<!-- 安全认证过滤器 -->
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
<property name="securityManager" ref="securityManager" /><!--
<property name="loginUrl" value="${cas.server.url}?service=${cas.project.url}${adminPath}/cas" /> -->
<property name="loginUrl" value="${adminPath}/login" />
<property name="successUrl" value="${adminPath}?login" />
<property name="filters">
<map>
<entry key="cas" value-ref="casFilter"/>
<entry key="authc" value-ref="formAuthenticationFilter"/>
</map>
</property>
<property name="filterChainDefinitions">
<ref bean="shiroFilterChainDefinitions"/>
</property>
</bean>
<!-- CAS认证过滤器 -->
<bean id="casFilter" class="org.apache.shiro.cas.CasFilter">
<property name="failureUrl" value="${adminPath}/login"/>
</bean>
<!-- 定义Shiro安全管理配置 -->
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
<property name="realm" ref="systemAuthorizingRealm" />
<property name="sessionManager" ref="sessionManager" />
<property name="cacheManager" ref="shiroCacheManager" />
</bean>
<!-- 自定义会话管理配置 -->
<bean id="sessionManager" class="com.thinkgem.jeesite.common.security.shiro.session.SessionManager">
<property name="sessionDAO" ref="sessionDAO"/>
<!-- 会话超时时间,单位:毫秒 -->
<property name="globalSessionTimeout" value="${session.sessionTimeout}"/>
<!-- 定时清理失效会话, 清理用户直接关闭浏览器造成的孤立会话 -->
<property name="sessionValidationInterval" value="${session.sessionTimeoutClean}"/>
<!-- <property name="sessionValidationSchedulerEnabled" value="false"/> -->
<property name="sessionValidationSchedulerEnabled" value="true"/>
<property name="sessionIdCookie" ref="sessionIdCookie"/>
<property name="sessionIdCookieEnabled" value="true"/>
</bean>
<!-- 指定本系统SESSIONID, 默认为: JSESSIONID 问题: 与SERVLET容器名冲突, 如JETTY, TOMCAT 等默认JSESSIONID,
当跳出SHIRO SERVLET时如ERROR-PAGE容器会为JSESSIONID重新分配值导致登录会话丢失! -->
<bean id="sessionIdCookie" class="org.apache.shiro.web.servlet.SimpleCookie">
<constructor-arg name="name" value="jeesite.session.id"/>
</bean>
<!-- 自定义Session存储容器 -->
<!-- <bean id="sessionDAO" class="com.thinkgem.jeesite.common.security.shiro.session.JedisSessionDAO"> -->
<!-- <property name="sessionIdGenerator" ref="idGen" /> -->
<!-- <property name="sessionKeyPrefix" value="${redis.keyPrefix}_session_" /> -->
<!-- </bean> -->
<bean id="sessionDAO" class="com.thinkgem.jeesite.common.security.shiro.session.CacheSessionDAO">
<property name="sessionIdGenerator" ref="idGen" />
<property name="activeSessionsCacheName" value="activeSessionsCache" />
<property name="cacheManager" ref="shiroCacheManager" />
</bean>
<!-- 定义授权缓存管理器 -->
<!-- <bean id="shiroCacheManager" class="com.thinkgem.jeesite.common.security.shiro.cache.SessionCacheManager" /> -->
<bean id="shiroCacheManager" class="org.apache.shiro.cache.ehcache.EhCacheManager">
<property name="cacheManager" ref="cacheManager"/>
</bean>
<!-- 保证实现了Shiro内部lifecycle函数的bean执行 -->
<bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/>
<!-- AOP式方法级权限检查 -->
<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>
在上面的配置中每次开启了sessionManager都会出问题在这里将它注释掉了。
其次,上面中的配置也是将credentialsMatcher没有加入了,这种方式适用于没有对密码进行处理的情况。
其中CustomRealm的配置是重点。
4 自定义Realm编码
CustomRealm如下:自定义relam是shiro的核心代码之一,在这里做了认证授权
授权的做法就是查找该用户下的所有角色,并把角色相关的权限标识放到 授权信息 SimpleAuthorizationInfo
中就可以了
/**
* Copyright © 2012-2014 <a href="https://www.mycomm.com/mycommcrm">MyComm CRM</a> All rights reserved.
*/
package com.thinkgem.jeesite.modules.sys.security;
import java.io.Serializable;
import java.util.Collection;
import java.util.List;
import javax.annotation.PostConstruct;
import org.apache.commons.lang3.StringUtils;
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.credential.HashedCredentialsMatcher;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.Permission;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.support.DefaultSubjectContext;
import org.apache.shiro.util.ByteSource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import com.thinkgem.jeesite.common.config.Global;
import com.thinkgem.jeesite.common.servlet.ValidateCodeServlet;
import com.thinkgem.jeesite.common.utils.Encodes;
import com.thinkgem.jeesite.common.utils.SpringContextHolder;
import com.thinkgem.jeesite.common.web.Servlets;
import com.thinkgem.jeesite.modules.sys.entity.Menu;
import com.thinkgem.jeesite.modules.sys.entity.Role;
import com.thinkgem.jeesite.modules.sys.entity.User;
import com.thinkgem.jeesite.modules.sys.service.SystemService;
import com.thinkgem.jeesite.modules.sys.utils.LogUtils;
import com.thinkgem.jeesite.modules.sys.utils.UserUtils;
import com.thinkgem.jeesite.modules.sys.web.LoginController;
/**
* 系统安全认证实现类
* @author MyComm
* @version 2014-7-5
*/
@Service
//@DependsOn({"userDao","roleDao","menuDao"})
public class SystemAuthorizingRealm extends AuthorizingRealm {
private Logger logger = LoggerFactory.getLogger(getClass());
private SystemService systemService;
/**
* 认证回调函数, 登录时调用
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authcToken) {
UsernamePasswordToken token = (UsernamePasswordToken) authcToken;
int activeSessionSize = getSystemService().getSessionDao().getActiveSessions(false).size();
if (logger.isDebugEnabled()){
logger.debug("login submit, active session size: {}, username: {}, password: {}", activeSessionSize, token.getUsername(), token.getPassword());
}
// 校验登录验证码
if (LoginController.isValidateCodeLogin(token.getUsername(), false, false)){
Session session = UserUtils.getSession();
String code = (String)session.getAttribute(ValidateCodeServlet.VALIDATE_CODE);
if (token.getCaptcha() == null || !token.getCaptcha().toUpperCase().equals(code)){
throw new AuthenticationException("msg:验证码错误, 请重试.");
}
}
// 校验用户名密码
User user = getSystemService().getUserByLoginName(token.getUsername());
if (user != null) {
if (Global.NO.equals(user.getLoginFlag())){
throw new AuthenticationException("msg:该已帐号禁止登录.");
}
byte[] salt = Encodes.decodeHex(user.getPassword().substring(0,16));
SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(new Principal(user, token.isMobileLogin(), token.getExtNum(),token.getIsReady(),token.getIsCheckin(),token.getSeatTel()),
user.getPassword().substring(16), ByteSource.Util.bytes(salt), getName());
return authenticationInfo;
} else {
return null;
}
}
/**
* 授权查询回调函数, 进行鉴权但缓存中无用户的授权信息时调用
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
Principal principal = (Principal) getAvailablePrincipal(principals);
// 获取当前已登录的用户
if (!Global.TRUE.equals(Global.getConfig("user.multiAccountLogin"))){
Collection<Session> sessions = getSystemService().getSessionDao().getActiveSessions(true, principal, UserUtils.getSession());
if (sessions.size() > 0){
// 如果是登录进来的,则踢出已在线用户
if (UserUtils.getSubject().isAuthenticated()){
User user = new User();
for (Session session : sessions){
if(session.getAttribute(DefaultSubjectContext.PRINCIPALS_SESSION_KEY)!=null){
user= UserUtils.get(session.getAttribute(DefaultSubjectContext.PRINCIPALS_SESSION_KEY).toString());
}
if(null!=user && null!=principal && (principal.getId()).equals(user.getId())){
getSystemService().getSessionDao().delete(session);
}
}
}
// 记住我进来的,并且当前用户已登录,则退出当前用户提示信息。
else{
UserUtils.getSubject().logout();
throw new AuthenticationException("msg:账号已在其它地方登录,请重新登录。");
}
}
}
User user = getSystemService().getUserByLoginName(principal.getLoginName());
if (user != null) {
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
List<Menu> list = UserUtils.getMenuList();
for (Menu menu : list){
if (StringUtils.isNotBlank(menu.getPermission())){
// 添加基于Permission的权限信息
for (String permission : StringUtils.split(menu.getPermission(),",")){
info.addStringPermission(permission);
}
}
}
// 添加用户权限
info.addStringPermission("user");
// 添加用户角色信息
for (Role role : user.getRoleList()){
info.addRole(role.getEnname());
}
// 更新登录IP和时间
getSystemService().updateUserLoginInfo(user);
// 记录登录日志
LogUtils.saveLog(Servlets.getRequest(), "系统登录");
return info;
} else {
return null;
}
}
@Override
protected void checkPermission(Permission permission, AuthorizationInfo info) {
authorizationValidate(permission);
super.checkPermission(permission, info);
}
@Override
protected boolean[] isPermitted(List<Permission> permissions, AuthorizationInfo info) {
if (permissions != null && !permissions.isEmpty()) {
for (Permission permission : permissions) {
authorizationValidate(permission);
}
}
return super.isPermitted(permissions, info);
}
@Override
public boolean isPermitted(PrincipalCollection principals, Permission permission) {
authorizationValidate(permission);
return super.isPermitted(principals, permission);
}
@Override
protected boolean isPermittedAll(Collection<Permission> permissions, AuthorizationInfo info) {
if (permissions != null && !permissions.isEmpty()) {
for (Permission permission : permissions) {
authorizationValidate(permission);
}
}
return super.isPermittedAll(permissions, info);
}
/**
* 授权验证方法
* @param permission
*/
private void authorizationValidate(Permission permission){
// 模块授权预留接口
}
/**
* 设定密码校验的Hash算法与迭代次数
*/
@PostConstruct
public void initCredentialsMatcher() {
HashedCredentialsMatcher matcher = new HashedCredentialsMatcher(SystemService.HASH_ALGORITHM);
matcher.setHashIterations(SystemService.HASH_INTERATIONS);
setCredentialsMatcher(matcher);
}
///**
//* 清空用户关联权限认证,待下次使用时重新加载
//*/
//public void clearCachedAuthorizationInfo(Principal principal) {
//SimplePrincipalCollection principals = new SimplePrincipalCollection(principal,
getName());
//clearCachedAuthorizationInfo(principals);
//}
/**
* 清空所有关联认证
* @Deprecated 不需要清空,授权缓存保存到session中
*/
@Deprecated
public void clearAllCachedAuthorizationInfo() {
//Cache<Object, AuthorizationInfo> cache = getAuthorizationCache();
//if (cache != null) {
//for (Object key : cache.keys()) {
//cache.remove(key);
//}
//}
}
/**
* 获取系统业务对象
*/
public SystemService getSystemService() {
if (systemService == null){
systemService = SpringContextHolder.getBean(SystemService.class);
}
return systemService;
}
/**
* 授权用户信息
*/
public static class Principal implements Serializable {
private static final long serialVersionUID = 1L;
private String id; // 编号
private String loginName; // 登录名
private String name; // 姓名
private String extNum; //分机
private String isReady; //自动就绪
private String isCheckin; //自动签入
private String seatTel; //座席电话
private boolean mobileLogin; // 是否手机登录
//private Map<String, Object> cacheMap;
public Principal(User user, boolean mobileLogin, String extNum, String isReady, String isCheckin,String seatTel) {
this.id = user.getId();
this.loginName = user.getLoginName();
this.name = user.getName();
this.mobileLogin = mobileLogin;
this.extNum = extNum;
this.isReady = isReady;
this.isCheckin = isCheckin;
this.seatTel = seatTel;
}
public String getId() {
return id;
}
public String getLoginName() {
return loginName;
}
public String getName() {
return name;
}
public String getExtNum() {
return extNum;
}
public String getIsReady() {
return isReady;
}
public String getIsCheckin() {
return isCheckin;
}
public String getSeatTel() {
return seatTel;
}
public void setSeatTel(String seatTel) {
this.seatTel = seatTel;
}
public boolean isMobileLogin() {
return mobileLogin;
}
//@JsonIgnore
//public Map<String, Object> getCacheMap() {
//if (cacheMap==null){
//cacheMap = new HashMap<String, Object>();
//}
//return cacheMap;
//}
/**
* 获取SESSIONID
*/
public String getSessionid() {
try{
return (String) UserUtils.getSession().getId();
}catch (Exception e) {
return "";
}
}
@Override
public String toString() {
return id;
}
}
}
}
5 缓存配置
ehcache.xml代码如下:[html] view
plain copy
<ehcache updateCheck="false" name="shiroCache">
<defaultCache
maxElementsInMemory="10000"
eternal="false"
timeToIdleSeconds="120"
timeToLiveSeconds="120"
overflowToDisk="false"
diskPersistent="false"
diskExpiryThreadIntervalSeconds="120"
/>
</ehcache>
通过使用ehache中就避免第次都向服务器发送权限授权(doGetAuthorizationInfo)的请求。
6.自定义表单编码过滤器
CustomFormAuthenticationFilter代码,认证之前调用,可用于验证码校验[java] view
plain copy
public class CustomFormAuthenticationFilter extends FormAuthenticationFilter {
// 原FormAuthenticationFilter的认证方法
@Override
protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
// 在这里进行验证码的校验
// 从session获取正确验证码
HttpServletRequest httpServletRequest = (HttpServletRequest) request;
HttpSession session = httpServletRequest.getSession();
// 取出session的验证码(正确的验证码)
String validateCode = (String) session.getAttribute("validateCode");
// 取出页面的验证码
// 输入的验证和session中的验证进行对比
String randomcode = httpServletRequest.getParameter("randomcode");
if (randomcode != null && validateCode != null && !randomcode.equals(validateCode)) {
// 如果校验失败,将验证码错误失败信息,通过shiroLoginFailure设置到request中
httpServletRequest.setAttribute("shiroLoginFailure", "randomCodeError");
// 拒绝访问,不再校验账号和密码
return true;
}
return super.onAccessDenied(request, response);
}
}
在此符上验证码jsp界面的代码
validatecode.jsp
[html] view
plain copy
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ page import="java.util.Random"%>
<%@ page import="java.io.OutputStream"%>
<%@ page import="java.awt.Color"%>
<%@ page import="java.awt.Font"%>
<%@ page import="java.awt.Graphics"%>
<%@ page import="java.awt.image.BufferedImage"%>
<%@ page import="javax.imageio.ImageIO"%>
<%
int width = 60;
int height = 32;
//create the image
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
Graphics g = image.getGraphics();
// set the background color
g.setColor(new Color(0xDCDCDC));
g.fillRect(0, 0, width, height);
// draw the border
g.setColor(Color.black);
g.drawRect(0, 0, width - 1, height - 1);
// create a random instance to generate the codes
Random rdm = new Random();
String hash1 = Integer.toHexString(rdm.nextInt());
// make some confusion
for (int i = 0; i < 50; i++) {
int x = rdm.nextInt(width);
int y = rdm.nextInt(height);
g.drawOval(x, y, 0, 0);
}
// generate a random code
String capstr = hash1.substring(0, 4);
//将生成的验证码存入session
session.setAttribute("validateCode", capstr);
g.setColor(new Color(0, 100, 0));
g.setFont(new Font("Candara", Font.BOLD, 24));
g.drawString(capstr, 8, 24);
g.dispose();
//输出图片
response.setContentType("image/jpeg");
out.clear();
out = pageContext.pushBody();
OutputStream strm = response.getOutputStream();
ImageIO.write(image, "jpeg", strm);
strm.close();
%>
7.登录控制器方法
[java] viewplain copy
/**
* 到登录界面
*
* @return
* @throws Exception
*/
@RequestMapping("login.do")
public String adminPage(HttpServletRequest request) throws Exception {
// 如果登陆失败从request中获取认证异常信息,shiroLoginFailure就是shiro异常类的全限定名
String exceptionClassName = (String) request.getAttribute("shiroLoginFailure");
// 根据shiro返回的异常类路径判断,抛出指定异常信息
if (exceptionClassName != null) {
if (UnknownAccountException.class.getName().equals(exceptionClassName)) {
// 最终会抛给异常处理器
throw new CustomJsonException("账号不存在");
} else if (IncorrectCredentialsException.class.getName().equals(exceptionClassName)) {
throw new CustomJsonException("用户名/密码错误");
} else if ("randomCodeError".equals(exceptionClassName)) {
throw new CustomJsonException("验证码错误 ");
} else {
throw new Exception();// 最终在异常处理器生成未知错误
}
}
// 此方法不处理登陆成功(认证成功),shiro认证成功会自动跳转到上一个请求路径
// 登陆失败还到login页面
return "admin/login";
}
8.用户回显Controller
当用户登录认证成功后,CustomRealm在调用完doGetAuthenticationInfo时,通过[java] view
plain copy
AuthenticationInfo authcInfo = new SimpleAuthenticationInfo(adminUser, password, this.getName());
return authcInfo;
SimpleAuthenticationInfo构造参数的第一个参数传入一个用户的对象,之后,可通过Subject subject = SecurityUtils.getSubject();中的subject.getPrincipal()获取到此对象。
所以需要回显用户信息时,我这样调用的
[java] view
plain copy
@RequestMapping("index.do")
public String index(Model model) {
//从shiro的session中取activeUser
Subject subject = SecurityUtils.getSubject();
//取身份信息
TAdminUser adminUser = (TAdminUser) subject.getPrincipal();
//通过model传到页面
model.addAttribute("adminUser", adminUser);
return "admin/index";
}
9.在jsp页面中控制权限
先引入shiro的头文件[html] view
plain copy
<!-- shiro头引入 -->
<%@ taglib uri="http://shiro.apache.org/tags" prefix="shiro"%>
采用shiro标签对权限进行处理
[html] view
plain copy
<!-- 有curd权限才显示修改链接,没有该 权限不显示,相当 于if(hasPermission(curd)) -->
<shiro:hasPermission name="curd">
<BR />
我拥有超级的增删改查权限额
</shiro:hasPermission>
10.在Controller控制权限
通过@RequiresPermissions注解,指定执行此controller中某个请求方法需要的权限[java] view
plain copy
@RequiresPermissions("sys:role:edit")
//需要有修改角色的权限
@RequestMapping(value = "delete")
public String delete(Role role, RedirectAttributes redirectAttributes,HttpServletRequest request) {
11.MD5加密加盐处理
这里以修改密码为例,通过获取新的密码(明文)后通过MD5加密+加盐+6次加密为例[java] view
plain copy
@RequestMapping("updatePassword.do")
@ResponseBody
public String updateAdminUserPassword(String newPassword) {
// 从shiro的session中取activeUser
Subject subject = SecurityUtils.getSubject();
// 取身份信息
TAdminUser adminUser = (TAdminUser) subject.getPrincipal();
// 生成salt,随机生成
SecureRandomNumberGenerator secureRandomNumberGenerator = new SecureRandomNumberGenerator();
String salt = secureRandomNumberGenerator.nextBytes().toHex();
Md5Hash md5 = new Md5Hash(newPassword, salt, 6);
String newMd5Password = md5.toHex();
// 设置新密码
adminUser.setPassword(newMd5Password);
// 设置盐
adminUser.setSalt(salt);
adminUserService.updateAdminUserPassword(adminUser);
return newPassword;
}
这是菜单权限树,想为哪个角色赋什么样的权限只需勾选相应的按钮就可以了。(下一篇说说我总结的数据范围过滤)
相关文章推荐
- 简单扩展shiro 实现NOT、AND、OR权限验证(支持复杂一点的表达式)
- [置顶] Shiro权限验证最详细的代码流转分析
- shiro框架---关于用户登录和权限验证功能的实现步骤(七)
- [置顶] 【一】Springboot+Shiro+Mybatis+Thymeleaf实现权限控制和gif验证
- 解决shiro注释 超越权限问题
- linux下常见的权限问题及验证
- shiro权限验证标签
- 简单两步快速实现shiro的配置和使用,包含登录验证、角色验证、权限验证以及shiro登录注销流程
- shiro 权限验证 AuthorizingRealm doGetAuthorizationInfo
- shiro 用户权限管理(2)-----注册md5加密,登录验证
- 简单shiro扩展实现NOT、AND、OR权限验证
- 使用shiro进行系统身份验证-权限控制,登录界面乱跳
- shiro权限健康安全验证框架
- JAVA自定义注解 和 运行时靠 反射获取注解,解决 shiro 注解型权限因子获取问题
- 简单三步理解Shiro权限验证/登录
- spring mvc整合shiro登录 权限验证
- shiro权限验证标签
- SpringBoot 集成 shiro权限验证
- SQL Server Reporting Services 用户不具有所需的权限。请验证授予了足够的权限并且解决了 Windows 用户帐户控制(UAC)限制问题。
- shiro权限验证标签