目录
一、授权
1、设置account拥有add权限才能访问
package com.zibo.config;
import com.sun.org.apache.regexp.internal.RE;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.LinkedHashMap;
@Configuration
public class ShiroConfig {
//1、创建Realm对象,需要自定义
@Bean
public AccountRealm accountRealm(){
return new AccountRealm();
}
//2、DefaultWebSecurityManager
@Bean(name = "securityManager")
public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("accountRealm")AccountRealm accountRealm){
DefaultWebSecurityManager manager = new DefaultWebSecurityManager();
//关联accountRealm
manager.setRealm(accountRealm);
return manager;
}
//3、ShiroFilterFactoryBean
@Bean(name = "shiroFilterFactoryBean")
public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("securityManager")DefaultWebSecurityManager manager){
ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();
//设置安全管理器
bean.setSecurityManager(manager);
//添加shiro内置过滤器
/*
* anon:无需认证就可以访问;
* authc:必须认证了才能访问;
* user:必须拥有记住我功能才能访问(一般不用);
* perms:拥有对某个资源的权限才能访问;
* role:拥有某个角色权限才能访问;
*/
LinkedHashMap<String, String> filterMap = new LinkedHashMap<>();
//★★★授权:只有account:add权限的账户才能访问
//注意:注意这是一个有序map,需要卸载拦截前面,否则不生效!!!
filterMap.put("/account/add","perms[account:add]");
//拦截:设置认证了才能访问
filterMap.put("/account/*","authc");
bean.setFilterChainDefinitionMap(filterMap);
//设置登录页面
bean.setLoginUrl("/toLogin");
return bean;
}
}
2、测试结果(访问add.html页面)
(我们目前并没有给任何账户添加这个权限)
二、若未授权则跳转到一个指定的页面
1、在MyController添加一个跳转方法
package com.zibo.controller;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.subject.Subject;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
public class MyController {
@RequestMapping({"/","/index"})
public String toIndex(Model model){
model.addAttribute("msg","Hello Shiro!");
return "index";
}
@RequestMapping("/account/add")
public String add(){
return "account/add";
}
@RequestMapping("/account/update")
public String update(){
return "account/update";
}
@RequestMapping("/toLogin")
public String toLogin(){
return "login";
}
@RequestMapping("/login")
public String login(String username,String password,Model model){
//获取当前的Subject
Subject subject = SecurityUtils.getSubject();
//封装用户的登录数据
UsernamePasswordToken token = new UsernamePasswordToken(username, password);
//登录
try{
subject.login(token);
return "index";
}catch (UnknownAccountException e){//用户名不存在
model.addAttribute("msg","用户名不存在!");
return "login";
} catch (IncorrectCredentialsException ice) {//密码错误
model.addAttribute("msg","密码错误!");
return "login";
} catch (LockedAccountException lae) {//用户被锁定
model.addAttribute("msg","用户被锁定!");
return "login";
}catch (AuthenticationException ae) {//认证异常:最大的异常,兜底
model.addAttribute("msg","认证异常!");
return "login";
}
}
@RequestMapping("/noauth")
@ResponseBody
public String unauthorized(){
return "未授权,无法访问此页面!";
}
}
2、在ShiroConfig类中设置未授权跳转的页面
package com.zibo.config;
import com.sun.org.apache.regexp.internal.RE;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.LinkedHashMap;
@Configuration
public class ShiroConfig {
//1、创建Realm对象,需要自定义
@Bean
public AccountRealm accountRealm(){
return new AccountRealm();
}
//2、DefaultWebSecurityManager
@Bean(name = "securityManager")
public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("accountRealm")AccountRealm accountRealm){
DefaultWebSecurityManager manager = new DefaultWebSecurityManager();
//关联accountRealm
manager.setRealm(accountRealm);
return manager;
}
//3、ShiroFilterFactoryBean
@Bean(name = "shiroFilterFactoryBean")
public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("securityManager")DefaultWebSecurityManager manager){
ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();
//设置安全管理器
bean.setSecurityManager(manager);
//添加shiro内置过滤器
/*
* anon:无需认证就可以访问;
* authc:必须认证了才能访问;
* user:必须拥有记住我功能才能访问(一般不用);
* perms:拥有对某个资源的权限才能访问;
* role:拥有某个角色权限才能访问;
*/
LinkedHashMap<String, String> filterMap = new LinkedHashMap<>();
//授权:只有account:add权限的账户才能访问
//注意:注意这是一个有序map,需要卸载拦截前面,否则不生效!!!
filterMap.put("/account/add","perms[account:add]");
//拦截:设置认证了才能访问
filterMap.put("/account/*","authc");
bean.setFilterChainDefinitionMap(filterMap);
//设置登录页面
bean.setLoginUrl("/toLogin");
//★★★设置未授权页面
bean.setUnauthorizedUrl("/noauth");
return bean;
}
}
3、测试结果
三、将权限授予用户
1、修改AccountRealm类,进行授权
package com.zibo.config;
import com.zibo.pojo.Account;
import com.zibo.service.AccountService;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.beans.factory.annotation.Autowired;
import java.util.List;
//自定义的AccountRealm,需要继承AuthorizingRealm
public class AccountRealm extends AuthorizingRealm {
@Autowired
AccountService accountService;
//授权
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
System.out.println("执行了授权方法doGetAuthorizationInfo!");
//★★★授权
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
//授权user:add
info.addStringPermission("account:add");
return info;
}
//认证
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
System.out.println("执行了认证方法doGetAuthenticationInfo!");
UsernamePasswordToken accountToken = (UsernamePasswordToken)authenticationToken;
//我们这里不该这么写的,我们应该写一个通过用户名查询的方法,但是既然都写到这了,就这么写吧
List<Account> all = accountService.findAll();
String tokenUsername = accountToken.getUsername();
boolean haveThisAccount = false;
String password = null;
for (Account account : all) {
if(account.getName().equals(tokenUsername)){
//说明存在这个用户名
haveThisAccount = true;
//我们假装其钱数就是其密码
password = String.valueOf(account.getMoney());
System.out.println(password);
break;
}
}
if(!haveThisAccount){
return null;//抛出异常,用户名不存在
}
//密码认证,shiro做
return new SimpleAuthenticationInfo("",password,"");
}
}
2、测试结果
四、给指定用户授权(判断即可)
(这里简化操作,我们假定如果用户名为“訾博”,咱就授权给他)
1、修改AccountRealm类
package com.zibo.config;
import com.zibo.pojo.Account;
import com.zibo.service.AccountService;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import java.util.List;
//自定义的AccountRealm,需要继承AuthorizingRealm
public class AccountRealm extends AuthorizingRealm {
@Autowired
AccountService accountService;
//授权
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
System.out.println("执行了授权方法doGetAuthorizationInfo!");
//授权
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
//★★★拿到当前登录的对象
Subject subject = SecurityUtils.getSubject();
//这是取的是下面存的:new SimpleAuthenticationInfo(tokenUsername,password,"");
Account account = (Account)subject.getPrincipal();
//这里简化操作,我们假定如果用户名为“訾博”,咱就授权给他
//真是业务中,从数据库中获取权限信息进行授权即可
if(account.getName().equals("訾博")){
//授权user:add
info.addStringPermission("account:add");
}
return info;
}
//认证
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
System.out.println("执行了认证方法doGetAuthenticationInfo!");
UsernamePasswordToken accountToken = (UsernamePasswordToken)authenticationToken;
//我们这里不该这么写的,我们应该写一个通过用户名查询的方法,但是既然都写到这了,就这么写吧
List<Account> all = accountService.findAll();
String tokenUsername = accountToken.getUsername();
boolean haveThisAccount = false;
String password = null;
Account thisAccount = null;
for (Account account : all) {
if(account.getName().equals(tokenUsername)){
//说明存在这个用户名
haveThisAccount = true;
thisAccount = account;
//我们假装其钱数就是其密码
password = String.valueOf(account.getMoney());
System.out.println(password);
break;
}
}
if(!haveThisAccount){
return null;//抛出异常,用户名不存在
}
//★★★密码认证,shiro做,传tokenUsername
return new SimpleAuthenticationInfo(thisAccount,password,"");
}
}
2、测试结果
五、用户注销
1、在MyController类中添加注销方法
package com.zibo.controller;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.subject.Subject;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
public class MyController {
@RequestMapping({"/","/index"})
public String toIndex(Model model){
model.addAttribute("msg","Hello Shiro!");
return "index";
}
@RequestMapping("/account/add")
public String add(){
return "account/add";
}
@RequestMapping("/account/update")
public String update(){
return "account/update";
}
@RequestMapping("/toLogin")
public String toLogin(){
return "login";
}
@RequestMapping("/login")
public String login(String username,String password,Model model){
//获取当前的Subject
Subject subject = SecurityUtils.getSubject();
//封装用户的登录数据
UsernamePasswordToken token = new UsernamePasswordToken(username, password);
//登录
try{
subject.login(token);
return "index";
}catch (UnknownAccountException e){//用户名不存在
model.addAttribute("msg","用户名不存在!");
return "login";
} catch (IncorrectCredentialsException ice) {//密码错误
model.addAttribute("msg","密码错误!");
return "login";
} catch (LockedAccountException lae) {//用户被锁定
model.addAttribute("msg","用户被锁定!");
return "login";
}catch (AuthenticationException ae) {//认证异常:最大的异常,兜底
model.addAttribute("msg","认证异常!");
return "login";
}
}
@RequestMapping("/noauth")
@ResponseBody
public String unauthorized(){
return "未授权,无法访问此页面!";
}
//注销
@RequestMapping("/logout")
@ResponseBody
public String logout(){
//获取当前的Subject
Subject subject = SecurityUtils.getSubject();
//注销
subject.logout();
return "注销成功!";
}
}
2、修改首页index.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>首页</h1>
<p th:text="${msg}"></p>
<a th:href="@{/account/add}">add</a>
<a th:href="@{/account/update}">update</a>
<a th:href="@{/logout}">注销</a>
</body>
</html>
3、测试结果