前面一個小節完成基本的配置,後面一個小節重點放在認證(登陸)和授權
- UserHandler.java
package cn.zzu.wcj.shiro.handler;
import javax.servlet.http.HttpSession;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.LockedAccountException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import cn.zzu.wcj.shiro.service.ShiroService;
@Controller
@RequestMapping("/Shiro")
public class UserHandler {
@Autowired
private ShiroService shiroService ;
@RequestMapping("doLogin")
public String doLogin(@RequestParam String userName,@RequestParam String password){
Subject currentUser = SecurityUtils.getSubject();
System.out.println(userName+"###############"+password);
if (!currentUser.isAuthenticated()) {
//把用戶賬號和密碼封裝成令牌
UsernamePasswordToken token = new UsernamePasswordToken(userName, password);
System.out.println("############1.Token"+token.hashCode());
//設置記住我
token.setRememberMe(true);
try {
//執行登陸
currentUser.login(token);
//若賬戶不存在,則Shiro會拋出UnknownAccountException異常
} catch (UnknownAccountException uae) {
System.out.println("##############用戶名錯誤!"+uae);
//若賬戶存在,但密碼不存在,則拋出IncorrectCredentialsException異常
} catch (IncorrectCredentialsException ice) {
System.out.println("##############密碼錯誤!"+ice);
//若賬戶被鎖定,就拋出LockedAccountException異常
} catch (LockedAccountException lae) {
System.out.println("##############賬戶鎖定!"+lae);
//所有認證時異常的父類
}catch (AuthenticationException ae) {
System.out.println("##############登陸錯誤!"+ae);
}catch(Exception e){
System.out.println("##################"+e);
}
}
return "redirect:/list.jsp" ;
}
@RequestMapping("/testAnno")
public String testAnno(HttpSession session){
session.setAttribute("wcj","java");
this.shiroService.sayHello();
return "redirect:/list.jsp" ;
}
}
- ShiroRealm.java
package cn.zzu.wcj.shiro.realm;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.LockedAccountException;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
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.util.ByteSource;
public class ShiroRealm extends AuthorizingRealm {
/**
* @see 授權會被 shiro 回調的方法
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(
PrincipalCollection principals) {
System.out.println("#################################################授權回調");
//1. 從 PrincipalCollection 中來獲取登錄用戶的信息
Object userName=principals.getPrimaryPrincipal() ;
//2. 利用登錄的用戶的信息來用戶當前用戶的角色或權限(可能需要查詢數據庫)
Set<String> roles=new HashSet<String>() ;
roles.addAll(Arrays.asList("user")) ;
//3. 創建 SimpleAuthorizationInfo, 並設置其 reles 屬性.
SimpleAuthorizationInfo info=new SimpleAuthorizationInfo(roles) ;
return info ;
}
/**
* @see 此方法是用來完成認證(即登陸功能的)
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(
AuthenticationToken token) throws AuthenticationException {
System.out.println("############[UsernamePasswordRealm]2.Token"+token);
SimpleAuthenticationInfo authcInfo=null ;
//1.將AuthenticationToken強轉成UsernamePasswordToken
UsernamePasswordToken upToken=(UsernamePasswordToken) token;
//2.獲取用戶名
String userName=upToken.getUsername() ;
//3.與數據庫中用戶名進行比對
if("unknow".equals(userName)){
throw new UnknownAccountException("用戶名不存在") ; //拋出用戶名錯誤異常
}
if("ghost".equals(userName)){
throw new LockedAccountException("用戶被鎖定") ;
}
//4.將數據庫中查詢到的用戶名和密碼放置到SimpleAuthenticationInfo中
//1)Object principal 用戶認證信息,即用戶名,
//2)Object credentials 用戶密碼,
//3)String realmName Real名稱,通過getName取得
Object principal="admin" ;
Object credentials="02bad5ac06ea6ce0be3a24fd39781d11" ;
String realmName=super.getName() ; //調用父類獲取Realm名稱的方法
ByteSource credentialsSalt=ByteSource.Util.bytes(userName); //鹽值加密
authcInfo=new SimpleAuthenticationInfo(principal, credentials, credentialsSalt, realmName);
return authcInfo;
}
}
- ShiroService.java
package cn.zzu.wcj.shiro.service;
import java.util.Date;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authz.annotation.Logical;
import org.apache.shiro.authz.annotation.RequiresRoles;
import org.apache.shiro.session.Session;
import org.springframework.stereotype.Service;
@Service
public class ShiroService {
@RequiresRoles(value={"admin","user"},logical=Logical.OR)
public void sayHello(){
System.out.println("Hello World !!! "+new Date());
Session session = SecurityUtils.getSubject().getSession();
System.out.println("############wcj-->"+session.getAttribute("wcj"));
}
}
Tips:上面的這些代碼看懂了就可以快速搭建Shiro安全框架,你看不懂並不代表我看不懂,我粘貼一下就可以在項目中跑起來,OK?想學習就不要浮躁