一.认识shiro
- 是一种安全框架。
二.使用shiro进行权限控制的流程
- Step1: 导入shiro的相关的jar包
- Step2: 准备好3个shiro工具类
- Md5Util.java 用于对密码进行加密处理
- AuthcredentiaMacher.java加密匹配器,用于对输入的明文进行加密处理
- AuthRealm.java 材料类,用于给登录提供素材,给权限控制提供素材
- Step3:在spring的配置文件中对配置5个bean的,分别是安全管理器,Realm原材料,加密匹配器,权限认证通知,shiro过滤工厂
- Step4: 在web.xml中实现配置shiro权限的过滤器
- Step5: 在controller实现中登录和登出逻辑的处理
- step6: 在对应的jsp中使用shiro标签实现对应内容的权限控制。
三.用shiro实现登录和登出和权限控制
(一)登录的处理
1. 导入权限控制shiro相关的jar包
<!-- Apache Shiro 权限架构 -->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-all</artifactId>
<version>1.2.3</version>
</dependency>
2. 在spring的配置文件applicationContent-shiro中添加5个bean的配置信息
<!--1. 安全管理器 -->
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
<!--注入原材料属性 -->
<property name="realm" ref="authRealm"></property>
</bean>
<!--2. 注入Realm原材料-->
<bean id="authRealm" class="cn.tedu.shiro.AuthRealm">
<!--注入自定义的加密匹配器 -->
<property name="credentialsMatcher" ref="authcredentialMacher"></property>
</bean>
<!--3.加密匹配器 -->
<bean id="authcredentialMacher" class="cn.tedu.shiro.AuthcredentialMacher"> </bean>
<!--4.权限认证通知 -->
<bean id="advisor" class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">
<!-- 注入安全管理器 -->
<property name="securityManager" ref="securityManagee"></property>
</bean>
<!--5.shiro过滤工厂 -->
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean" >
<!-- 注入安全管理器 -->
<property name="secrityManager" ref="securityManager"></property>
<!-- 注入登录地址 -->
<property name="loginUrl" value="/tologin"></property>
<!-- 注入拦截地址和放行地址 -->
<property name="filterChainDefinitions">
<value>
<!-- 放行登录按钮的请求地址 -->
/login.action=anno
<!-- 放行所有静态资源文件 -->
/staticfile/**=anno
<!-- 拦截剩下的所有 -->
/**authc
</value>
</property>
</bean>
3. 在web.xml文件中 配置shiro过滤器
<!-- 配置shiro的过滤器 -->
<filter>
<!-- 此处name一定要和spring配置文件中的过滤工厂id一致 -->
<filter-name>shiroFilter</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
<!-- 配置让shiro的过滤工厂的生命周期 交由web容器进行管理 -->
<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>
4. 在登录controller中创建subject对象
//1.创建Subject
Subject subject = SecurityUtils.getSubject();
//2.创建用户名密码的令牌
UsernamePasswordToken token = new UsernamePasswordToken(userName, password);
//3.登录
try {
//如果成功 则无异常 登录失败会抛出异常
subject.login(token);
//得到详细用户对象存到session中
User user = (User) subject.getPrincipal();
user = userService.findOne(user.getUserId());
session.setAttribute("_CURRENT_USER", user);
return "redirect:/home.action";
} catch (AuthenticationException exception) {//登录失败
model.addAttribute("errorInfo", "用户名或密码错误!");
model.addAttribute("username", userName);
model.addAttribute("password",password);
return "sysadmin/login/login";
}
5. 提前准备好,下面3个类:
- 在AuthRealm.java类,继承SimpleAccountRealm.java;重写其中的第一个方法,需要传入正确的用户对象,正确的用户密码,原材料的名称
public class AuthRealm extends SimpleAccountRealm{
@Autowired
private UserService userService;
//给登录提供素材
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) {
UsernamePasswordToken upToken=(UsernamePasswordToken) token;
//principal:正确的用户对象
User user =userService.findUserByUsername(upToken.getUsername());
//credentials:正确的用户密码
//realmName:原材料类的名称
AuthenticationInfo info=new
SimpleAuthenticationInfo(
user,user.getPassword(),this.getName());
return info;
}
Service层:
@Override
public User findUserByUsername(String username) {
return userMapper.findUserByUsername(username);
}
Dao层:
@Select("select * from user_p where username=#username")
public User findUserByUsername(String username);
- Md5Utils加密类:
public class Md5Utils{
public static String getMd5(String password){
Md5Hash md5Hash = new Md5Hash(password, "tedu", 3);
return md5Hash.toString();
}
}
- AuthcredentialMacher.java加密匹配器类:在加密匹配器中 把token中明文密码加密成密文放token中
//加密匹配器,需要调用Md5Utils对输入的密码进行加密后和数据库中比较验证
public class AuthcredentialMacher extends SimpleCredentialsMatcher{ public boolean doGredentialsMatch(AuthenticationToken token,AuthenticationInfo info){
UsernamePasswordToken uptoken =(UsernamePasswordToken) token;
//对用户输入的密码进行加密
String newPassword = Md5Utils.getMd5(String.valueOf(uptoken.getPassword()));
//把加密后的密码设置回token中
uptoken.setPassword(newPassword.toCharArray());
return super.doCredentialsMatch(token, info);
}
(二)实现shiro进行权限控制
- 在AuthRealm.java类,继承SimpleAccountRealm.java;重写其中的第二个方法; 给安全管理器提供当前用户有哪些权限
//给权限控制提供素材
@Override
protected AuthorizationInfo doGetAuthorizationInfo(
PrincipalCollection principals) {
SimpleAuthorizationInfo info =new SimpleAuthorizationInfo();
User user =(User) principals.getPrimaryPrincipal();
List<String> list =userService.findModuleName(user.getUserId());
info.addStringPermissions(list);
return info;
}
2. 在jsp页面中通过shiro标签对页面进行判断处理 例如: 对这几个模块进行权限控制判断
1) 添加shiro的@taglib头文件
< %@ taglib uri="http://shiro.apache.org/tags" prefix="shiro"%>
2)对需要进行权限判的模块使用shiro标签进行处理
<div id="menuContent">
<shiro:authenticated name="系统管理">
<span id="topmenu" onclick="toModule('home');">系统首页</span><span id="tm_separator"></span>
</shiro:authenticated>
<shiro:authenticated name="货运管理">
<span id="topmenu" onclick="toModule('cargo');">货运管理</span><span id="tm_separator"></span>
</shiro:authenticated>
<shiro:authenticated name="基础信息">
<span id="topmenu" onclick="toModule('baseinfo');">基础信息</span><span id="tm_separator"></span>
</shiro:authenticated>
<shiro:authenticated name="系统管理">
<span id="topmenu" onclick="toModule('sysadmin');">系统管理</span>
</shiro:authenticated>
</div>