jfinal 整合shiro的使用

时间:2022-04-22 18:21:13
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";
}
}