springboot集成shiro 实现权限控制

来源:互联网 发布:js文本超出显示省略号 编辑:程序博客网 时间:2024/06/13 06:48

shiro

apache shiro 是一个轻量级的身份验证与授权框架,与spring security 相比较,简单易用,灵活性高,springboot本身是提供了对security的支持,毕竟是自家的东西。springboot暂时没有集成shiro,这得自己配。

shiro 内置过滤器

请看博文:
http://blog.csdn.net/hxpjava1/article/details/7035724

本文实现:

本文实现从数据库读取用户信息,获取当前用户的权限或角色,通过配置文件过滤用户的角色或权限。拥有相应的角色或者相应的权限的用户可以访问相应的url。

数据库设计

这里写图片描述

1. 添加依赖

  <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>        <dependency>            <groupId>com.github.theborakompanioni</groupId>            <artifactId>thymeleaf-extras-shiro</artifactId>            <version>1.2.1</version>        </dependency>

2. 添加shiro 配置

package com.us.shiro;import org.apache.shiro.authc.credential.HashedCredentialsMatcher;import org.apache.shiro.spring.LifecycleBeanPostProcessor;import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;import org.apache.shiro.spring.web.ShiroFilterFactoryBean;import org.apache.shiro.web.filter.authc.LogoutFilter;import org.apache.shiro.web.mgt.DefaultWebSecurityManager;import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.context.annotation.DependsOn;import javax.servlet.Filter;import java.util.LinkedHashMap;import java.util.Map;/** * shiro配置类 * Created by cdyoue on 2016/10/21. */@Configurationpublic class ShiroConfiguration {    /**     * LifecycleBeanPostProcessor,这是个DestructionAwareBeanPostProcessor的子类,     * 负责org.apache.shiro.util.Initializable类型bean的生命周期的,初始化和销毁。     * 主要是AuthorizingRealm类的子类,以及EhCacheManager类。     */    @Bean(name = "lifecycleBeanPostProcessor")    public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {        return new LifecycleBeanPostProcessor();    }    /**     * HashedCredentialsMatcher,这个类是为了对密码进行编码的,     * 防止密码在数据库里明码保存,当然在登陆认证的时候,     * 这个类也负责对form里输入的密码进行编码。     */    @Bean(name = "hashedCredentialsMatcher")    public HashedCredentialsMatcher hashedCredentialsMatcher() {        HashedCredentialsMatcher credentialsMatcher = new HashedCredentialsMatcher();        credentialsMatcher.setHashAlgorithmName("MD5");        credentialsMatcher.setHashIterations(2);        credentialsMatcher.setStoredCredentialsHexEncoded(true);        return credentialsMatcher;    }    /**ShiroRealm,这是个自定义的认证类,继承自AuthorizingRealm,     * 负责用户的认证和权限的处理,可以参考JdbcRealm的实现。     */    @Bean(name = "shiroRealm")    @DependsOn("lifecycleBeanPostProcessor")    public ShiroRealm shiroRealm() {        ShiroRealm realm = new ShiroRealm();//        realm.setCredentialsMatcher(hashedCredentialsMatcher());        return realm;    }//    /**//     * EhCacheManager,缓存管理,用户登陆成功后,把用户信息和权限信息缓存起来,//     * 然后每次用户请求时,放入用户的session中,如果不设置这个bean,每个请求都会查询一次数据库。//     *///    @Bean(name = "ehCacheManager")//    @DependsOn("lifecycleBeanPostProcessor")//    public EhCacheManager ehCacheManager() {//        return new EhCacheManager();//    }    /**     * SecurityManager,权限管理,这个类组合了登陆,登出,权限,session的处理,是个比较重要的类。//     */    @Bean(name = "securityManager")    public DefaultWebSecurityManager securityManager() {        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();        securityManager.setRealm(shiroRealm());//        securityManager.setCacheManager(ehCacheManager());        return securityManager;    }    /**     * ShiroFilterFactoryBean,是个factorybean,为了生成ShiroFilter。     * 它主要保持了三项数据,securityManager,filters,filterChainDefinitionManager。     */    @Bean(name = "shiroFilter")    public ShiroFilterFactoryBean shiroFilterFactoryBean() {        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();        shiroFilterFactoryBean.setSecurityManager(securityManager());        Map<String, Filter> filters = new LinkedHashMap<>();        LogoutFilter logoutFilter = new LogoutFilter();        logoutFilter.setRedirectUrl("/login");//        filters.put("logout",null);        shiroFilterFactoryBean.setFilters(filters);        Map<String, String> filterChainDefinitionManager = new LinkedHashMap<String, String>();        filterChainDefinitionManager.put("/logout", "logout");        filterChainDefinitionManager.put("/user/**", "authc,roles[ROLE_USER]");//用户为ROLE_USER 角色可以访问。由用户角色控制用户行为。        filterChainDefinitionManager.put("/events/**", "authc,roles[ROLE_ADMIN]");        //        filterChainDefinitionManager.put("/user/edit/**", "authc,perms[user:edit]");// 这里为了测试,固定写死的值,也可以从数据库或其他配置中读取,此处是用权限控制        filterChainDefinitionManager.put("/**", "anon");        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionManager);        shiroFilterFactoryBean.setSuccessUrl("/");        shiroFilterFactoryBean.setUnauthorizedUrl("/403");        return shiroFilterFactoryBean;    }    /**     * DefaultAdvisorAutoProxyCreator,Spring的一个bean,由Advisor决定对哪些类的方法进行AOP代理。     */    @Bean    @ConditionalOnMissingBean    public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {        DefaultAdvisorAutoProxyCreator defaultAAP = new DefaultAdvisorAutoProxyCreator();        defaultAAP.setProxyTargetClass(true);        return defaultAAP;    }    /**     * AuthorizationAttributeSourceAdvisor,shiro里实现的Advisor类,     * 内部使用AopAllianceAnnotationsAuthorizingMethodInterceptor来拦截用以下注解的方法。     */    @Bean    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor() {        AuthorizationAttributeSourceAdvisor aASA = new AuthorizationAttributeSourceAdvisor();        aASA.setSecurityManager(securityManager());        return aASA;    }}

3. 添加Realm 验证

package com.us.shiro;import com.us.bean.Permission;import com.us.bean.Role;import com.us.bean.User;import com.us.dao.PermissionDao;import com.us.dao.UserDao;import org.apache.shiro.SecurityUtils;import org.apache.shiro.authc.*;import org.apache.shiro.authz.AuthorizationInfo;import org.apache.shiro.authz.SimpleAuthorizationInfo;import org.apache.shiro.realm.AuthorizingRealm;import org.apache.shiro.session.Session;import org.apache.shiro.subject.PrincipalCollection;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.beans.factory.annotation.Autowired;/** * Created by cdyoue on 2016/10/21. */public class ShiroRealm extends AuthorizingRealm {    private Logger logger =  LoggerFactory.getLogger(this.getClass());    @Autowired    private UserDao userService;    @Autowired    private PermissionDao permissionService;    @Override    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {        logger.info("doGetAuthorizationInfo+"+principalCollection.toString());        User user = userService.getByUserName((String) principalCollection.getPrimaryPrincipal());        //把principals放session中 key=userId value=principals        SecurityUtils.getSubject().getSession().setAttribute(String.valueOf(user.getId()),SecurityUtils.getSubject().getPrincipals());        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();        //赋予角色        for(Role userRole:user.getRoles()){            info.addRole(userRole.getName());        }        //赋予权限        for(Permission permission:permissionService.getByUserId(user.getId())){//            if(StringUtils.isNotBlank(permission.getPermCode()))                info.addStringPermission(permission.getName());        }        //设置登录次数、时间//        userService.updateUserLogin(user);        return info;    }    @Override    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {        logger.info("doGetAuthenticationInfo +"  + authenticationToken.toString());        UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;        String userName=token.getUsername();        logger.info(userName+token.getPassword());        User user = userService.getByUserName(token.getUsername());        if (user != null) {//            byte[] salt = Encodes.decodeHex(user.getSalt());//            ShiroUser shiroUser=new ShiroUser(user.getId(), user.getLoginName(), user.getName());            //设置用户session            Session session = SecurityUtils.getSubject().getSession();            session.setAttribute("user", user);            return new SimpleAuthenticationInfo(userName,user.getPassword(),getName());        } else {            return null;        }//        return null;    }}

4. 添加controller

package com.us.controller;import org.apache.shiro.SecurityUtils;import org.apache.shiro.authc.AuthenticationException;import org.apache.shiro.authc.UsernamePasswordToken;import org.apache.shiro.subject.Subject;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.web.bind.annotation.*;import java.util.HashMap;import java.util.Map;/** * Created by cdyoue on 2016/10/21. * 登陆控制器 */@RestControllerpublic class LoginController {    private Logger logger = LoggerFactory.getLogger(this.getClass());    @RequestMapping(value = "/login", method = RequestMethod.POST)    public String login(            @RequestParam(value = "username", required = true) String userName,            @RequestParam(value = "password", required = true) String password,            @RequestParam(value = "rememberMe", required = true, defaultValue = "false") boolean rememberMe    ) {        logger.info("==========" + userName + password + rememberMe);        Subject subject = SecurityUtils.getSubject();        UsernamePasswordToken token = new UsernamePasswordToken(userName, password);        token.setRememberMe(rememberMe);        try {            subject.login(token);        } catch (AuthenticationException e) {            e.printStackTrace();//            rediect.addFlashAttribute("errorText", "您的账号或密码输入错误!");            return "{\"Msg\":\"您的账号或密码输入错误\",\"state\":\"failed\"}";        }        return "{\"Msg\":\"登陆成功\",\"state\":\"success\"}";    }    @RequestMapping("/")    @ResponseBody    public String index() {        return "no permission";    }}

此处代码不全,只是写了springboot 整合的主要类,如果需要全部代码请移步。。。

源码:https://github.com/527515025/springBoot

1 0
原创粉丝点击