1. 程式人生 > >Springboot+SpringMVC+Myabtis整合shiro許可權控制

Springboot+SpringMVC+Myabtis整合shiro許可權控制

最近也被這個難題搞的我頭都大了額。寫下此篇文章獻給自己和廣大朋友。如果有不懂的地方可以加企鵝號詢問哦。

企鵝號:2054861587,不一定會時時在,但如果有空的話就會給你回答

maven依賴:

<dependency>
    <groupId>org.apache.shiro</groupId>
    <artifactId>shiro-spring</artifactId>
    <version>1.2.5</version>
</dependency>
<dependency>
    <groupId>org.apache.shiro</groupId>
    <artifactId>shiro-ehcache</artifactId>
    <version>1.2.5</version>
</dependency>

專案下面新建Shiro配置類。

以下為配置類程式碼:

這裡有個坑,也是這個坑讓我頭疼了好久,就是當你沒有寫自定義的ShiroRealm類時,下面程式碼會瘋狂報錯。

ps:親,記得哦。ShiroRealm類的程式碼在後面。

@Configuration
public class ShiroConfiguration {
    @Bean(name = "lifecycleBeanPostProcessor")
    public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
        return new LifecycleBeanPostProcessor();
    }

    @Bean(name = "shiroRealm")
    @DependsOn("lifecycleBeanPostProcessor")
    public ShiroRealm shiroRealm() {
        ShiroRealm realm = new ShiroRealm();
        return realm;
    }

    @Bean(name = "ehCacheManager")
    @DependsOn("lifecycleBeanPostProcessor")
    public EhCacheManager ehCacheManager() {
        EhCacheManager ehCacheManager = new EhCacheManager();
        return ehCacheManager;
    }

    @Bean("securityManager")
    public DefaultWebSecurityManager securityManager() {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        securityManager.setRealm(shiroRealm());
        securityManager.setCacheManager(ehCacheManager());//使用者授權/認證資訊Cache, 採用EhCache 快取
        return securityManager;
    }

    @Bean(name = "shiroFilter")
    public ShiroFilterFactoryBean shiroFilterFactoryBean(DefaultWebSecurityManager securityManager) {
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        shiroFilterFactoryBean.setSecurityManager(securityManager());
        System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
        Map<String, String> filterChainDefinitionManager = new LinkedHashMap<>();
        filterChainDefinitionManager.put("/logout", "logout");
        filterChainDefinitionManager.put("/user/**", "authc,roles[user]");
        filterChainDefinitionManager.put("/shop/**", "authc,roles[shop]");
        filterChainDefinitionManager.put("/admin/**", "authc,roles[admin]");
        filterChainDefinitionManager.put("/login", "anon");//anon 可以理解為不攔截
        filterChainDefinitionManager.put("/ajaxLogin", "anon");//anon 可以理解為不攔截
        filterChainDefinitionManager.put("/static/**", "anon");//靜態資源不攔截
        //filterChainDefinitionManager.put("/**", "authc,roles[user]");//其他資源全部攔截
        filterChainDefinitionManager.put("/**", "anon");
        // filterChainDefinitionManager.put("/controller/MangerController", "anon");
        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionManager);

        shiroFilterFactoryBean.setLoginUrl("/login");
        shiroFilterFactoryBean.setSuccessUrl("/");
        shiroFilterFactoryBean.setUnauthorizedUrl("/403");
        return shiroFilterFactoryBean;
    }

    @Bean
    @ConditionalOnBean
    public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
        DefaultAdvisorAutoProxyCreator daap = new DefaultAdvisorAutoProxyCreator();
        daap.setProxyTargetClass(true);
        return daap;
    }

    /**
     * 開啟shiro aop註解支援
     * 使用代理方式,所以需要開啟程式碼支援
     *
     * @param securityManager
     * @return
     */
    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(DefaultWebSecurityManager securityManager) {
        AuthorizationAttributeSourceAdvisor aasa = new AuthorizationAttributeSourceAdvisor();
        aasa.setSecurityManager(securityManager);
        return aasa;
    }
ShiroRealm類:

這裡的User、role、Permission為實體類,實體類程式碼最下面貼出,mangerService為實現層,下面也會放出程式碼。

public class ShiroRealm extends AuthorizingRealm {
    private Logger logger=LoggerFactory.getLogger(ShiroRealm.class);
    @Autowired
    private MangerService mangerService;


    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        logger.info("##################執行Shiro許可權認證##################");
        User user= (User) principalCollection.getPrimaryPrincipal();

        if(user!=null){
            SimpleAuthorizationInfo info=new SimpleAuthorizationInfo();
            //使用者的角色集合
           info.addRoles(user.getRolelist());
            //使用者的許可權集合
           info.addStringPermissions(user.getPerminslist());
            return info;
        }
        return null;
    }


    /**
     * 登入認證
     * @param authenticationToken
     * @return
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
       UsernamePasswordToken token= (UsernamePasswordToken) authenticationToken;
       logger.info("驗證當前SubJect時獲取到的token為:"+token.toString());
       User user=mangerService.getUser(token.getUsername());
        System.out.println(token.getUsername());
       if(user!=null){
            //若存在,將此使用者存放到登入認證info中,無需自己做密碼對比,Shiro會為我們進行密碼對比校驗
           List<Role> rlist = mangerService.findRoleByUid(user.getUS_ID());//獲取使用者角色
           List<Permission> plist = mangerService.findPermissionByUid((user.getUS_ID()));//獲取使用者許可權
           List<String> roleStrlist=new ArrayList<String>();////使用者的角色集合
           List<String> perminsStrlist=new ArrayList<String>();//使用者的許可權集合
           for (Role role : rlist) {
               roleStrlist.add(role.getName());
           }
           for (Permission permission : plist) {
               perminsStrlist.add(permission.getName());
           }
           user.setRolelist(roleStrlist);
           user.setPerminslist(perminsStrlist);
            Session session = SecurityUtils.getSubject().getSession();
            session.setAttribute("user", user);//成功則放入session
            //若存在,將此使用者存放到登入認證info中,無需自己做密碼對比,Shiro會為我們進行密碼對比校驗
           return new SimpleAuthenticationInfo(user, user.getUS_PASS(), getName());
       }
        return null;
    }
}

mangerService程式碼如下,其餘方法就不貼出了,只貼出上面ShiroRealm類呼叫的三個類:

public List<Role> findRoleByUid(String us_id) {
    return mdao.findRoleByUid(us_id);
}

public List<Permission> findPermissionByUid(String us_id) {
    return mdao.findPermissionByUid(us_id);
}

public User getUser(String username) {
    return mdao.getUser(username);
}

mdao程式碼如下:

public User getUser(String username);
List<Role> findRoleByUid(String us_id);

List<Permission> findPermissionByUid(String us_id);

都是最普通的程式碼,o(∩_∩)o 哈哈 下面上XML程式碼:

<select id="getUser" resultType="user" parameterType="String">
    select us_id,us_name,us_name_kp,us_pass from bas_user where us_name=#{param1}
</select>
<select id="findRoleByUid" resultType="Role" parameterType="String">
    select * from u_role where id=#{param1}
</select>
<select id="findPermissionByUid" resultType="Permission" parameterType="String">
    select * from u_permission where id=#{param1}
</select>
Controller層:
@RequestMapping(value = "/login")
public String login(HttpServletRequest request, HttpServletResponse response,Model model) {
    response.setContentType("text/html;charset=utf-8");
    String username = request.getParameter("username");
    String password = request.getParameter("password");
    UsernamePasswordToken usernamePasswordToken=new UsernamePasswordToken(username,password);
    Subject subject=SecurityUtils.getSubject();
    try {
    logger.info("對使用者["+username+"]開始進行登入驗證...驗證開始");
        subject.login(usernamePasswordToken);
    logger.info("對使用者[" + username + "]進行登入驗證..驗證通過");
    } catch (UnknownAccountException e) {
        logger.info("對使用者[" + username + "]進行登入驗證..驗證未通過,未知賬戶");
        logger.info("未知帳號");
    }catch (IncorrectCredentialsException ice){
        logger.info("對使用者[" + username + "]進行登入驗證..驗證未通過,錯誤的憑證");
        logger.info("密碼不正確");
    }catch(LockedAccountException lae){
        logger.info("對使用者[" + username + "]進行登入驗證..驗證未通過,錯誤的憑證");
        logger.info("帳戶已鎖定");
    }catch (AuthenticationException  e){
        logger.info("使用者名稱或密碼不正確");
    }
    User user= (User) subject.getPrincipal();
     return "index";
}

博主承認上面的程式碼有點繞,如果實在不懂,歡迎提問,或者你直接照抄也木有問題。

表結構的兄弟不要著急,相信你們看了實體類程式碼後也會建表了,如果還是不明白,那就請繼續往下面看,博主再說詳細些。

public class User {
    private String US_ID;  //使用者ID
    private String US_NAME; //使用者名稱
    private String US_PASS;  //密碼
    private List<String> rolelist;
    private List<String> perminslist;
以下省略N多的GET/SET/Tostring方法.
}
Role實體類:
private String id;
private String name;//角色名稱
private String type;//角色型別

pemins實體類:

private String id;
private String url;//url地址
private String name;//url描述

OK後臺程式碼搞定了。

資料庫表還不知道怎麼建的同學,看著博主的 實體類。String或int 為資料庫的資料型別,

user表當中沒有rolelist、perminslist。只有使用者ID、使用者名稱、密碼

user表當中沒有rolelist、perminslist。只有使用者ID、使用者名稱、密碼

user表當中沒有rolelist、perminslist。只有使用者ID、使用者名稱、密碼

重要的事情說三遍。

還不懂?那就舉個例子咯:

pemins實體類舉例。

private String id;

private String url;//url地址

private String name;//url描述

那麼我們在資料庫當中應該這麼定義:

create table pemis(

id  varchar(20),

url varchar(50),

name varchar(80)

)

那麼pemins這個表我們就新建好了,有幾個實體類就有幾張表,親。如果還不會,額去找你的資料庫老師吧。

JSP頁面呼叫:

<%@ taglib prefix="shiro" uri="http://shiro.apache.org/tags" %>

放在最上面,不要問為啥,我就是要勵志站在頂端的男人。

<shiro:authenticated>使用者已經登入顯示此內容<br/></shiro:authenticated><br/>

<shiro:hasRole name="manager">manager角色登入顯示此內容<br/></shiro:hasRole>

<shiro:hasRole name="admin">admin角色登入顯示此內容<br/></shiro:hasRole>

<shiro:hasRole name="normal">normal角色登入顯示此內容<br/>

</shiro:hasRole><br/> <shiro:hasAnyRoles name="manager,admin">manager or admin 角色使用者登入顯示此內容<br/>

</shiro:hasAnyRoles><br/> <shiro:principal/>-顯示當前登入使用者名稱<br/><br/>

<shiro:hasPermission name="add">add許可權使用者顯示此內容<br/>

</shiro:hasPermission> <shiro:hasPermission name="user:query">user:query許可權使用者顯示此內容<br/>

</shiro:hasPermission>

<shiro:lacksPermission name="user:query">不具有user:query許可權的使用者顯示此內容 <br/></shiro:lacksPermission>

OK,恭喜你成功了