《一,認證》數據庫
1.先建兩個class文件session
一個寫 AuthRealm (受權與認證方法,並繼承) extends AuthorizingRealm app
獲取其默認方法doGetAuthorizationInfo(受權方法) doGetAuthenticationInfo(認證方法) jsp
一個寫PasswordMatcher(密碼驗證器,並繼承) extends SimpleCredentialsMatcheride
獲取默認方法doCredentialsMatch 工具
2.在Action的登陸方法中 ui
@Action("loginAction_login")//重頁面跳轉過來的路徑名加密
public String login() throws Exception {對象
//判斷用戶名是否是爲空,若是是說明沒有登陸,跳轉到用戶登陸頁面blog
if(UtilFuns.isEmpty(username)){
return "login";
}
//1.SecurityUtils:是shiro的一個工具類。經過SecurityUtils獲取getSubject 獲得一個返回值
Subject subject = SecurityUtils.getSubject();
//3.根據邏輯2。new一個 UsernamePasswordToken,並傳上用戶名及密碼。把返回值傳給登入做爲條件。
UsernamePasswordToken token = new UsernamePasswordToken(username,password);
try {
//2. subject的返回值裏有兩個方法logout:登出 login:登入。這裏咱們使用登陸方法,經過方法咱們能夠看到須要一個返回值:AuthenticationToken的類型,又由於AuthenticationToken 是一個接口,因此咱們使用他下面的UsernamePasswordToken 的實現類來寫(ps:查看方法:Ctrl+t),
subject.login(token);//當調用subject的登入方法時,會跳轉到認證的方法上。。。。。。。。。。
//4.在證方法中subject已經把獲取到了用戶,因此咱們用subject.getPrincipal 能夠獲取到登陸的用戶,Principal:他是在認證方法中的principal:主要對象(登陸的用戶,詳情看認證方法return的哪一步註釋)
User user = (User) subject.getPrincipal();
//5.把user用戶數據經過Session.put放在session值棧中。SysConstant.CURRENT_USER_INFO:是一個返回的值,在jsp頁面中能夠接收到,也能夠直接寫一個字符串讓頁面接收,返回的數據能夠在頁面作回顯等功能
session.put(SysConstant.CURRENT_USER_INFO, user);
return SUCCESS;//以上所有都過了後,讓其訪問頁面數據
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
super.put("errorInfo", "您的用戶名或密碼錯誤"); //登陸頁面的錯誤信息提示
return "login";
}
}
//退出
@Action("loginAction_logout")
public String logout(){
session.remove(SysConstant.CURRENT_USER_INFO); //刪除session
SecurityUtils.getSubject().logout(); //調用登出方法
return "logout";
}
3.在認證方法中的doGetAuthenticationInfo
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken arg0) throws AuthenticationException {
// TODO Auto-generated method stub
System.out.println("調用認證方法");
UsernamePasswordToken token =(UsernamePasswordToken)arg0;//先將arg0強轉爲UsernamePasswordToken類型
final String username = token.getUsername();//經過token獲取到用戶名
Specification<User> spec = new Specification<User>() { //把username 設爲查詢條件,查詢數據庫是否有這個用戶名
@Override
public Predicate toPredicate(Root<User> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
// TODO Auto-generated method stub
return cb.equal(root.get("username").as(String.class),username);
}
};
List<User> find = userServiceimpl.find(spec); //把spec 條件放到 查詢中查詢數據 查詢用戶名
if(find!=null&& find.size()>0){ //判斷返回的結果不爲空,及返回的數不小於0
User user = find.get(0); //經過索引獲取到返回值的第一個數中的數據
return new SimpleAuthenticationInfo(user, user.getPassword(), getName()) ;//這裏若是上面的都成立後會return到密碼校驗哪裏去
/* SimpleAuthenticationInfo:是doGetAuthenticationInfo的一個實現類,由於doGetAuthenticationInfo 是一個接口不能直接new
把返回值添加到條件中 //principal:主要對象(登陸的用戶) , credentials:密碼 ,realm的名字能夠經過getName獲取類名做爲區分 */
}
return null;
}
4.在密碼檢驗中PasswordMatcher
public class PasswordMatcher extends SimpleCredentialsMatcher { //先實現一個接口SimpleCredentialsMatcher 獲取doCredentialsMatch的內部方法
@Override
public boolean doCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) {
System.out.println("調用了密碼對比器");
UsernamePasswordToken utoken = (UsernamePasswordToken) token;
/*[把AuthenticationToken 中的token 裝換爲AuthenticationToken 中的(ps:查看方法Ctrl+t)
UsernamePasswordToken實現類 由於AuthenticationToken 是接口不能new數據],*/
String pwd = new String(utoken.getPassword());//經過utoken 獲取用戶密碼,並轉換成String類型,注意這裏的轉換不能強轉,要用new的方法
//source:要加密的內容 salt:增長複雜度的內容 哈希次數:2
Md5Hash md5Hash = new Md5Hash(pwd, utoken.getUsername(), 2); //調用Md5加密 爲輸入的數據加密
String credentials = (String)info.getCredentials(); //經過AuthenticationInfo 的info 查詢數據庫的密碼 裝換成String類型
return equals(md5Hash.toString(),credentials); //對比用戶輸入的數據和數據庫密碼是否一致。return走,返回到Action方法中。
}
}
5.執行流程圖
《二,受權》
1.在受權方法中
@Overrideprotected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) { System.out.println("受權"); SimpleAuthorizationInfo simpleAuthorizationInfo=new SimpleAuthorizationInfo(); Set<String> permissionSet = new HashSet<>(); Set<String> roleNameSet = new HashSet<>(); ShiroUser shiroUser = (ShiroUser) principalCollection.getPrimaryPrincipal(); List<Integer> roleList = shiroUser.getRoleList(); for (Integer roleId : roleList) { List<String> permissions = roleMenuMapper.findPermissionsByRoleId(roleId); if (permissions != null) { for (String permission : permissions) { if (StringUtils.isNotEmpty(permission)) { permissionSet.add(permission); } } } String roleName = roleMapper.findRoleNameByRoleId(roleId); roleNameSet.add(roleName); } simpleAuthorizationInfo.addStringPermissions(permissionSet); simpleAuthorizationInfo.addRoles(roleNameSet); //查詢登陸用戶的全部角色的權限 return simpleAuthorizationInfo;}