1. 程式人生 > >jfinal 整合shiro的使用

jfinal 整合shiro的使用

meaven 專案轉化為 web 專案並在 tomcat 釋出過程:http://www.cnblogs.com/zhanggl/p/4733654.html




shiro 筆記


1.shiro jar匯入 


                 <dependency>
   <groupId>org.apache.shiro</groupId>
   <artifactId>shiro-core</artifactId>
   <version>1.4.0</version>
</dependency>


       <!-- https://mvnrepository.com/artifact/org.apache.shiro/shiro-web -->
<dependency>
   <groupId>org.apache.shiro</groupId>
   <artifactId>shiro-web</artifactId>
   <version>1.4.0</version>
</dependency>
2.shiro.ini 檔案




  
[main]
#realm  自定 義 realm 
shiroDbRealm=common.shiro.ShiroDbRealm
securityManager.realms = $shiroDbRealm
# 預設起始頁
authc.loginUrl = /passport/
# 登入成功跳轉路徑 可以自己定義
authc.successUrl = /index
# 退出跳轉路徑
logout.redirectUrl = /passport/


#路徑角色許可權設定
[urls]
# /passport/captcha  /passport/login /resources/** 不需要認證就可以訪問
/passport/captcha = anon
/passport/login = anon
/resources/** = anon
/passport/logout = logout
# /** 所有路徑都要做認證
/** = authc




3.web.xml


            <listener>
   <listener-class>org.apache.shiro.web.env.EnvironmentLoaderListener</listener-class>
 </listener>

<filter>
   <filter-name>ShiroFilter</filter-name>
   <filter-class>org.apache.shiro.web.servlet.ShiroFilter</filter-class>
 </filter>
 <filter-mapping>
   <filter-name>ShiroFilter</filter-name>
   <url-pattern>/*</url-pattern>
  
 </filter-mapping>


4. shiro 啟動過程


 (1)在專案啟動時就會將需要許可權角色認證的action載入到記憶體,
 (2) 使用者登入,simpleUser 自己可以重寫,自定義引數。在使用者校驗通過就會把角色資訊放進登入使用者內,登入成功跳轉到成功頁。
 (3) 當前使用者訪問某個action 時 如果加了角色許可權認證 ,requireRoles 註解可以自己重寫 
    這個是擁有某個角色可以通過
   package common.shiro;


import org.apache.shiro.authz.annotation.Logical;


import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;


@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface RequiresRoles {
    String[] value();
    Logical logical() default Logical.OR; // 預設為or,可以是and 


 (4) action 用法 有其一個角色就可以訪問
 


   @RequiresRoles( value = {"04", "01"})
  public void look() {
System.err.println("您可以啊,能進來");
renderText("您可以啊,能進來");
}
}






  (5)自己重寫的 realm


package common.shiro;


import java.util.HashSet;
import java.util.List;
import java.util.Set;


import javax.annotation.Resource;


import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UnknownAccountException;
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 com.jfinal.plugin.activerecord.Record;


import common.entity.TRole;
import common.entity.Users;
import common.shiro.user.CaptchaUsernamePasswordToken;
import common.shiro.user.SimpleUser;


public class ShiroDbRealm extends AuthorizingRealm {
    Users dao=new Users().dao();
    TRole roleDao=new TRole().dao();
@Resource
//private UserService userService;

/**
* 當進行角色和許可權認證時走此方法
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
SimpleUser simpleUser = (SimpleUser) principals.fromRealm(getName()).iterator().next();
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
if (null == simpleUser) {
return info;
}
String sqlPara="select * from users where username=?";
Users user=dao.findFirst(sqlPara,simpleUser.getUsername());
if (null == user) {
return info;
}


/*List<SysOperate> oplist = shiroDao.getOperateByUserId(user.getId());// 獲取使用者所有的功能許可權
for (SysOperate o : oplist) {
info.addStringPermission(o.getPermission());// 獲取資源名稱
}*/
Set<String> roleNames = new HashSet<String>();
roleNames.add(simpleUser.getRole());
info.setRoles(roleNames);
return info;
}


/**
* 身份認證
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
CaptchaUsernamePasswordToken authcToken = (CaptchaUsernamePasswordToken) token;
String sqlPara="select * from users where username=?";
   //校驗使用者是否存在
Users user=dao.findFirst(sqlPara,authcToken.getUsername());
if (user != null) {
String password = String.valueOf(authcToken.getPassword());
//校驗使用者密碼是否正確
if (password.equals(user.getPassword())) {
SimpleUser simpleUser = new SimpleUser(user.getId(), user.getUsername());
TRole role=roleDao.findById(user.getFkRoleId());
//獲取使用者的角色名和角色,放進當前使用者登入的例項中 注意這可以不放,當用戶進行許可權角色認證時 還是走 上面的方法 AuthorizationInfo()
simpleUser.setRoleName(role.getRoleName());
simpleUser.setRole(role.getRoleNum());
return new SimpleAuthenticationInfo(simpleUser, password, getName());
} else {
throw new AuthenticationException("密碼錯誤");
}
} else {
throw new UnknownAccountException("使用者不存在");
}

}


}




(6)自己重寫 ShiroPlugin.java 自己定義頁面的跳轉路徑和action檢查


(7)ShiroInterceptor.java 自定義攔截器 對有添加註解action 進行校驗




package common.shiro;




import org.apache.shiro.authz.AuthorizationException;
import org.apache.shiro.authz.UnauthenticatedException;


import com.jfinal.aop.Interceptor;
import com.jfinal.aop.Invocation;
import com.jfinal.kit.StrKit;


public class ShiroInterceptor implements Interceptor {
/**
* 登入成功時所用的頁面。
*/
private final String loginUrl;


/**
* 許可權驗證失敗時所用的頁面。
*/
private final String unauthorizedUrl;

/**
* 儲存為登陸前的訪問頁面
*/
private final String savedRequestKey;

public ShiroInterceptor(){
this.loginUrl = ShiroKit.getLoginUrl();
this.unauthorizedUrl = ShiroKit.getUnauthorizedUrl();
this.savedRequestKey = ShiroKit.getSavedRequestKey();
}


public void intercept(Invocation ai) {


        AuthzHandler ah = ShiroKit.getAuthzHandler(ai.getActionKey());
        // 存在訪問控制處理器。
        if (ah != null) {
            //System.out.println("許可權控制器不為空--------------------------------------");
            try {


                // 執行許可權檢查。
                ah.assertAuthorized();
            } catch (UnauthenticatedException lae) {


                // RequiresGuest,RequiresAuthentication,RequiresUser,未滿足時,丟擲未經授權的異常。
                // 如果沒有進行身份驗證,返回HTTP401狀態碼,或者跳轉到預設登入頁面
                if (StrKit.notBlank(ShiroKit.getLoginUrl())) {
                    //儲存登入前的頁面資訊,只儲存GET請求。其他請求不處理。
                    if (ai.getController().getRequest().getMethod().equalsIgnoreCase("GET")) {
                        ai.getController().setSessionAttr(ShiroKit.getSavedRequestKey(), ai.getActionKey());
                    }
                    ai.getController().redirect(ShiroKit.getLoginUrl());
                } else {
                    ai.getController().renderError(401);
                }
                return;
            } catch (AuthorizationException ae) {
                // RequiresRoles,RequiresPermissions授權異常
                // 如果沒有許可權訪問對應的資源,返回HTTP狀態碼403,或者調轉到為授權頁面




                if (StrKit.notBlank(ShiroKit.getUnauthorizedUrl())) {


                    ai.getController().redirect(ShiroKit.getUnauthorizedUrl());
                } else {
                    ai.getController().renderError(403);
                }
                return;
            }
        }
//System.out.println("許可權控制器為空--------------------------------------");
        // 執行正常邏輯
        ai.invoke();
    }
}




(8)JFinalClubConfig.java 配置
//全域性攔截器


public void configInterceptor(Interceptors me) {
 //  me.add(new LoginSessionInterceptor());
    me.add(new ShiroInterceptor()); 
    }




 public void configPlugin(Plugins me) {
  //新增shiroPlugin 
        ShiroPlugin shiroPlugin = new ShiroPlugin(this.routes);
me.add(shiroPlugin);
  
    }




 public void configEngine(Engine me) {
    //配置全域性方法
    me.addDirective("hasRole",new shiroTagForHasRole());
    }


(9) 自定義的simpleUser




package common.shiro.user;


import java.io.Serializable;




public class SimpleUser implements Serializable{
private static final long serialVersionUID = 1L;
private final Integer id;
private final String username;
private final String name;
private String roleName;
private String role;
public SimpleUser(Integer id, String username,String name) {
this.id = id;
this.username = username;
this.name = name;
}


public SimpleUser(Integer id, String username) {
this.id = id;
this.username = username;
this.name = username;
}


public final Integer getId() {
return id;
}
/**
* @Title: getUsername  
* @Description: 獲得使用者名稱 
* @return 
* @since V1.0.0
*/
public final String getUsername() {
return username;
}
/**
* @Title: getRoleName  
* @Description: 獲得角色名稱 
* @return 
* @since V1.0.0
*/
public final String getRoleName() {
return roleName;
}
/**
* @Title: setRoleName  
* @Description: 設定角色名稱  
* @param roleName 
* @since V1.0.0
*/
public final void setRoleName(String roleName) {
this.roleName = roleName;
}
public final String getRole() {
return role;
}
public final void setRole(String role) {
this.role = role;
}
public String getName() {
return name;
}

}
(10) 全域性方法 是否擁有角色 或許可權 獲取當前使用者 等功能




package common.shiro;


import org.apache.shiro.SecurityUtils;
import org.apache.shiro.subject.Subject;


/**
 * ShiroMethod. (SPI, Singleton, ThreadSafe)
 *
 * @author dafei (myaniu AT gmail DOT com)
 */
public class ShiroMethod {


private static final String NAMES_DELIMETER = ",";


/**
* 禁止初始化
*/
private ShiroMethod() {}


/**
* 獲取 Subject
*
* @return Subject
*/
protected static Subject getSubject() {
return SecurityUtils.getSubject();
}


/**
* 驗證當前使用者是否屬於該角色?,使用時與lacksRole 搭配使用
*
* @param roleName
*            角色名
* @return 屬於該角色:true,否則false
*/
public static boolean hasRole(String roleName) {
return getSubject() != null && roleName != null
&& roleName.length() > 0 && getSubject().hasRole(roleName);
}


/**
* 與hasRole標籤邏輯相反,當用戶不屬於該角色時驗證通過。
*
* @param roleName
*            角色名
* @return 不屬於該角色:true,否則false
*/
public static boolean lacksRole(String roleName) {
return !hasRole(roleName);
}


/**
* 驗證當前使用者是否屬於以下任意一個角色。
*
* @param roleNames
*            角色列表
* @return 屬於:true,否則false
*/
public static boolean hasAnyRoles(String roleNames) {
boolean hasAnyRole = false;
Subject subject = getSubject();
if (subject != null && roleNames != null && roleNames.length() > 0) {
// Iterate through roles and check to see if the user has one of the
// roles
for (String role : roleNames.split(NAMES_DELIMETER)) {
if (subject.hasRole(role.trim())) {
hasAnyRole = true;
break;
}
}
}
return hasAnyRole;
}


/**
* 驗證當前使用者是否屬於以下所有角色。
*
* @param roleNames
*            角色列表
* @return 屬於:true,否則false
*/
public static boolean hasAllRoles(String roleNames) {
boolean hasAllRole = true;
Subject subject = getSubject();
if (subject != null && roleNames != null && roleNames.length() > 0) {
// Iterate through roles and check to see if the user has one of the
// roles
for (String role : roleNames.split(NAMES_DELIMETER)) {
if (!subject.hasRole(role.trim())) {
hasAllRole = false;
break;
}
}
}
return hasAllRole;
}


/**
* 驗證當前使用者是否擁有指定許可權,使用時與lacksPermission 搭配使用
*
* @param permission
*            許可權名
* @return 擁有許可權:true,否則false
*/
public static boolean hasPermission(String permission) {
return getSubject() != null && permission != null
&& permission.length() > 0
&& getSubject().isPermitted(permission);
}


/**
* 與hasPermission標籤邏輯相反,當前使用者沒有制定許可權時,驗證通過。
*
* @param permission
*            許可權名
* @return 擁有許可權:true,否則false
*/
public static boolean lacksPermission(String permission) {
return !hasPermission(permission);
}


/**
* 已認證通過的使用者。不包含已記住的使用者,這是與user標籤的區別所在。與notAuthenticated搭配使用
*
* @return 通過身份驗證:true,否則false
*/
public static boolean authenticated() {
return getSubject() != null && getSubject().isAuthenticated();
}


/**
* 未認證通過使用者,與authenticated標籤相對應。與guest標籤的區別是,該標籤包含已記住使用者。。
*
* @return 沒有通過身份驗證:true,否則false
*/
public static boolean notAuthenticated() {
return !authenticated();
}


/**
* 認證通過或已記住的使用者。與guset搭配使用。
*
* @return 使用者:true,否則 false
*/
public static boolean user() {
return getSubject() != null && getSubject().getPrincipal() != null;
}


/**
* 驗證當前使用者是否為“訪客”,即未認證(包含未記住)的使用者。用user搭配使用
*
* @return 訪客:true,否則false
*/
public static boolean guest() {
return !user();
}


/**
* 輸出當前使用者資訊,通常為登入帳號資訊。
* @return 當前使用者資訊
*/
public String principal(){
if (getSubject() != null) {
            // Get the principal to print out
            Object principal = getSubject().getPrincipal();
            return principal.toString();
        }
return "Guest";
}
}