篇幅较长可以通过右侧目录查看文章目录
shiro登录认证与授权案例
项目准备
4 授权-角色
4.1 在ok页面添加2个超链接
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h1>登录成功</h1>
<a href="/logout">注销</a><br />
<a href="/add">add</a>
<a href="/delete">delete</a>
</body>
</html>
4.2 UserController添加2个对应的方法
@RequestMapping("/add")
public String add(){
return "ok";
}
@RequestMapping("/delete")
public String delete(){
return "ok";
}
4.3 在UserRealm的授权方法AuthorizationInfo添加功能
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
SimpleAuthorizationInfo sazi = new SimpleAuthorizationInfo();
Object username = principalCollection.getPrimaryPrincipal();
if ("admin".equals(username.toString())){
HashSet<String> roles = new HashSet<String>();
roles.add("admin");
sazi.addRoles(roles);
}
return sazi;
}
4.3 在spring容器中配置roles过滤器
多个角色用逗号隔开
4.4 新建一个没有权限页面unauthorized.jsp
这里的login.jsp,ok.jsp,unauthorized.jsp都是在spring容器的shiroFilter中配置的
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h1>你没有权限</h1>
</body>
</html>
4.5 测试
使用admin2为用户名登录后,点击add会跳转到没有权限的页面
使用admin则成功调用
5. 授权-权限
5.1 在spring容器中配置权限过滤器
5.2 在UserRealm的授权方法doGetAuthorizationInfo添加功能
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
SimpleAuthorizationInfo sazi = new SimpleAuthorizationInfo();
Object username = principalCollection.getPrimaryPrincipal();
if ("admin".equals(username.toString())){
HashSet<String> roles = new HashSet<String>();
roles.add("admin");
sazi.addRoles(roles);
} else if ("admin2".equals(username.toString())){
HashSet<String> permissions = new HashSet<String>();
permissions.add("user:delete");
sazi.addStringPermissions(permissions);
}
return sazi;
}
5.3 测试
使用admin为用户名登录的话 可以调用add,调用delete会跳转到没有权限页面。
使用admin2为用户名登录的话 可以调用delete,调用add会跳转到没有权限页面。
6. 授权方式
6.1 注解
6.1.1 在controller方法上加注解
@RequiresPermissions(“user:add”)
@RequiresPermissions (value={“user:a”, “user:b”}, logical= Logical.OR):表示当前 Subject 需要权限 user:a 或 user:b
@RequiresRoles(“admin”)
@RequiresRoles(value={“admin”,“user”}, logical= Logical.AND):表示当前 Subject 需要角色 admin 和user
6.1.2 配置springmvc.xml
如果要使用注解使用,首先要在配置文件中开启注解(SpringMVC配置文件中)
<!-- 启动shiro注解 -->
<aop:config proxy-target-class="true"></aop:config>
<bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">
<property name="securityManager" ref="securityManager" />
</bean>
6.1.3 springmvc.xml配置全局异常处理
用注解如果没有权限不会自动跳到自己配的页面,会报错。
<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
<!-- 默认的错误视图页面 -->
<property name="defaultErrorView" value="error" />
<!-- 错误视图页面可以通过${ex}获取异常信息 -->
<property name="exceptionAttribute" value="ex" />
<property name="exceptionMappings">
<props>
<prop key="org.apache.shiro.authz.AuthorizationException">
unauthorized
</prop>
</props>
</property>
</bean>
6.2 jsp标签
6.2.1 导标签库
<%@ taglib uri="http://shiro.apache.org/tags" prefix="shiro" %>
标签
- 游客 : guest
<shiro:guest> 欢迎游客访问,<a href="/login.jsp">登录</a> </shiro:guest>
- 用户已经认证并且选择了记住我 : user
<shiro:user> 欢迎[<shiro:principal/>]登录,<a href="/logout">注销</a> </shiro:user>
- 用户已经认证没有选择了记住我 : authenticated
<shiro:authenticated> 用户[<shiro:principal/>]已身份验证通过 </shiro:authenticated>
- 显示用户信息 : principal
<shiro: principal/>
- 当前Subject有角色将显示body体内容 : hasRole
<shiro:hasRole name="admin"> 用户[<shiro:principal/>]拥有角色admin<br/> </shiro:hasRole>
- hasAnyRoles
<shiro:hasAnyRoles name="admin,user"> 用户[<shiro:principal/>]拥有角色admin或user<br/> </shiro:hasAnyRoles>
- 当前Subject没有角色将显示body体内容 : lacksRole
<shiro:lacksRole name="abc"> 用户[<shiro:principal/>]没有角色abc<br/> </shiro:lacksRole>
- 如果当前Subject有权限将显示body体内容 : hasPermission
<shiro:hasPermission name="user:create"> 用户[<shiro:principal/>]拥有权限user:create<br/> </shiro:hasPermission>
- 如果当前Subject没有权限将显示body体内容 : lacksPermission标签
<shiro:lacksPermission name="org:create"> 用户[<shiro:principal/>]没有权限org:create<br/> </shiro:lacksPermission>
7 记住我
7.1 修改登录页面
新增记住我选项
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h1>登录页面</h1>
<form action="/login">
username:<input type="text" name="username"><br />
password:<input type="text" name="password"><br />
rememberMe:<input type="checkbox" name="rememberMe"><br />
<input type="submit" value="登录">
</form>
</body>
</html>
7.2 修改控制器login方法
@RequestMapping("/login")
public String login(String username, String password, String rememberMe){
// 1. 获取当前用户
Subject currentUser = SecurityUtils.getSubject();
// *2. 判断是否登录,没有登陆返回false
if (!currentUser.isAuthenticated()) {
// 3。 封装用户名和密码
UsernamePasswordToken token = new UsernamePasswordToken(username, password);
try {
// 判断是否记住我
if("on".equals(rememberMe)){
token.setRememberMe(true);
}
// 4. 登录
currentUser.login(token);
} catch (AuthenticationException ae) { // 6.3.4 其他的认证异常
System.out.println("认证失败。。。。");
return "login";
}
}
return "ok";
}
7.3 修改applicationContext配置文件
加密记住我存在cookies中的数据
<!-- 会话Cookie模板 -->
<bean id="rememberMeCookie" class="org.apache.shiro.web.servlet.SimpleCookie">
<constructor-arg value="sid" />
<!--设置js是否可以访问cookie,true不能访问 -->
<property name="httpOnly" value="true" />
<!-- 保存时长30天,以秒为单位 -->
<property name="maxAge" value="2592000" />
</bean>
<!-- rememberMe管理器 -->
<bean id="rememberMeManager" class="org.apache.shiro.web.mgt.CookieRememberMeManager">
<!-- ipherKey是加密rememberMe Cookie的密钥;默认AES算法 -->
<property name="cipherKey" value="#{T(org.apache.shiro.codec.Base64).decode('4AvVhmFLUs0KTA3Kprsdag==')}" />
<!-- 引入上面定义的cookie模板 -->
<property name="cookie" ref="rememberMeCookie" />
</bean>
7.4 修改过滤器
7.5 测试
8 总结
8.1 登录认证
- realm
- 过滤器
8.2 控制权限
- 过滤器:没有权限会跳转到自己配置的页面
- 注解和标签:没有权限会抛异常
8.3 加密
- 盐值加密解决加密后密码一致问题