shiro整合springboot作为权限控制的学习

2019年7月16

最近在学习shiro关于权限控制这一块,对shiro理解了一些,有一部分知识点还没有弄清楚,先记录一部分的内容,之后会加以补充,直接上代码

1、pom.xm代码

<properties>
    <java.version>1.8</java.version>
    <mybatisplus.version>3.0.7.1</mybatisplus.version>
    <shiro.version>1.4.0</shiro.version>
</properties>
<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-thymeleaf</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <scope>runtime</scope>
    </dependency>
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <optional>true</optional>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>

    <dependency>
        <groupId>org.apache.shiro</groupId>
        <artifactId>shiro-core</artifactId>
        <version>${shiro.version}</version>
    </dependency>
    <dependency>
        <groupId>org.apache.shiro</groupId>
        <artifactId>shiro-spring</artifactId>
        <version>${shiro.version}</version>
    </dependency>
</dependencies>

 

2、ShiroConfig 配置文件,对拦截器的配置,自定义拦截类,也可以自定义记住密码类以及缓存类,这里面有一个坑,那就是SecurityManager类默认导入的类,有问题,需要自己引入import org.apache.shiro.mgt.SecurityManager;

OAuth2Realm类是自己定义的类,需要实现AuthorizingRealm

import org.apache.shiro.mgt.SecurityManager;
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.mgt.DefaultWebSecurityManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.servlet.Filter;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;

/**
 * Shiro配置
 *
 * @author Mark sunlightcs@gmail.com
 */
@Configuration
public class ShiroConfig {

    @Bean("securityManager")
    public SecurityManager securityManager(OAuth2Realm oAuth2Realm) {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        securityManager.setRealm(oAuth2Realm);
        securityManager.setRememberMeManager(null);
        return securityManager;
    }

    @Bean("shiroFilter")
    public ShiroFilterFactoryBean shirFilter(SecurityManager securityManager) {
        ShiroFilterFactoryBean shiroFilter = new ShiroFilterFactoryBean();
        shiroFilter.setSecurityManager(securityManager);
        Map<String, String> filterMap = new LinkedHashMap<>();
        //oauth过滤
        Map<String, Filter> filters = new HashMap<>();
        filters.put("oauth2", new OAuth2Filter());
        shiroFilter.setFilters(filters);
      /*  filterMap.put("/api/**", "roles[admin]");*/
        filterMap.put("/**", "oauth2");
        shiroFilter.setFilterChainDefinitionMap(filterMap);
        return shiroFilter;
    }

    @Bean("lifecycleBeanPostProcessor")
    public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
        return new LifecycleBeanPostProcessor();
    }

    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
        AuthorizationAttributeSourceAdvisor advisor = new AuthorizationAttributeSourceAdvisor();
        advisor.setSecurityManager(securityManager);
        return advisor;
    }

}
3、OAuth2Realm自定义类。重写用户身份认证方法和权限验证方法
@Component
public class OAuth2Realm extends AuthorizingRealm {
    @Autowired
    private ShiroService shiroService;
    /**
     * 授权(验证权限时调用)
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        System.out.println("————权限认证————");
        SysUserEntity user = (SysUserEntity)principals.getPrimaryPrincipal();
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        //获得该用户角色
        Set<String> set = new HashSet<>();
        //需要将 role 封装到 Set 作为 info.setRoles() 的参数
        set.add("user");
        //设置该用户拥有的角色
        info.setRoles(set);
        return info;
    }

    /**
     * 认证(登录时调用)
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        System.out.println("————身份认证方法————");
        UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;
        // 从数据库获取对应用户名密码的用户
        String userName = token.getUsername();
        SysUserEntity s = shiroService.getPassword(userName);
        if (null == s.getPassword()) {
            throw new AccountException("用户名不正确");
        } else if (! s.getPassword().equals(new String((char[]) token.getCredentials()))) {
            throw new AccountException("密码不正确");
        }
        return new SimpleAuthenticationInfo(token.getPrincipal(),  s.getPassword(), getName());
    }
}

4、自定义拦截类 ,在shiroConfig类中加入该拦截类,当需要走该拦截类时,会实现onAccessDenied方法

OAuth2Filter

 

5、其他工具类。可有可无,只是为了方便OAuth2Token 
public class OAuth2Token implements AuthenticationToken {
    private String token;

    public OAuth2Token(String token){
        this.token = token;
    }

    @Override
    public String getPrincipal() {
        return token;
    }

    @Override
    public Object getCredentials() {
        return token;
    }
}

6、controller方法(登录的controller)==验证权限这一块,没走通,不知道为什么没有走验证权限这个方法,如果密码正确,则返回login方法里的return信息,如果密码不正确或者用户名不正确,则走身份验证方法的异常类,

if (null == s.getPassword()) {
    throw new AccountException("用户名不正确");
} else if (! s.getPassword().equals(new String((char[]) token.getCredentials()))) {
    throw new AccountException("密码不正确");
}

如果用户名不正确,用Postman跑接口时,会返回用户名不正确的信息,如果密码不正确,则返回密码不正确的信息。

@RestController
@RequestMapping("/api")
public class LoginController {

    @Autowired
    private ShiroService shiroService;
    @RequestMapping(value = "/notLogin", method = RequestMethod.GET)
    public String notLogin() {
        return "您尚未登陆!";
    }



    @RequestMapping(value = "/notRole", method = RequestMethod.GET)
    public String notRole() {
        return "您没有权限!";
    }



    @RequestMapping(value = "/logout", method = RequestMethod.GET)
    public String logout() {
        Subject subject = SecurityUtils.getSubject();
        //注销
        subject.logout();
        return "成功注销!";
    }



    /**
     * 登陆
     *
     * @param username 用户名
     * @param password 密码
     */

    @RequestMapping(value = "/login", method = RequestMethod.GET)
    @RequiresPermissions("generator:stuhonor:save")
    public String login(String username, String password) {
        // 从SecurityUtils里边创建一个 subject
        Subject subject = SecurityUtils.getSubject();
        // 在认证提交前准备 token(令牌)
        UsernamePasswordToken token = new UsernamePasswordToken(username, password);
        // 执行认证登陆
        subject.login(token);
        System.out.println(subject.getPreviousPrincipals());
        System.out.println(subject.getPrincipal());//获取用户名
        System.out.println(subject.getPrincipals());//获取用户名
        subject.getSession().setAttribute("username",subject.getPrincipals());
        System.out.println(subject.getSession().getAttribute("username"));
        String role="admin";
        //根据权限,指定返回数据
        if ("user".equals(role)) {
            return "欢迎登陆";
        }
        if ("admin".equals(role)) {
         return "欢迎来到管理员页面";
        }
        return "权限错误!";
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值