springboot整合shiro与thymleaf实现登录和授权

1.pom文件

<dependencies>
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-spring-boot-web-starter</artifactId>
            <version>1.4.0</version>
        </dependency>

        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>1.3.2</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.47</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.1.0</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>

        <!--shrio和thymeleaf集成的扩展依赖,为了能在页面上使用xsln:shrio的标签 -->
        <dependency>
            <groupId>com.github.theborakompanioni</groupId>
            <artifactId>thymeleaf-extras-shiro</artifactId>
            <version>2.0.0</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-configuration-processor</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>

2.自定义Realm

@Slf4j
public class MyShiroRealm extends AuthorizingRealm {

    @Autowired
    private RoleService roleService;//角色模模块
    @Autowired
    private UserService userService;//用户模块
    @Autowired
    private PermissionService permissionService;//权限模块

    @Override
    public String getName() {
        return "myShiroRealm";
    }

    /**
     * 授权
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
        SysUser user  = (SysUser) principals.getPrimaryPrincipal();
        if (user == null) {
            log.error("授权失败,用户信息为空!!!");
            return null;
        }
        try {
            //获取用户角色集
            Set<String> listRole= roleService.findRoleByUsername(user.getUsername());
            simpleAuthorizationInfo.addRoles(listRole);
            //通过角色获取权限集
            for (String role : listRole) {
                Set<String> permission= permissionService.findPermissionByRole(role);
                simpleAuthorizationInfo.addStringPermissions(permission);
            }
            return simpleAuthorizationInfo;
        } catch (Exception e) {
            log.error("授权失败,系统内部错误!!!", e);
        }
        return simpleAuthorizationInfo;
    }

    /**
     * 登录
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        UsernamePasswordToken authToken = (UsernamePasswordToken) token;
        // 获取用户输入的账号
        String userName = authToken.getUsername();
        //通过账号查找用户信息
        SysUser user = userService.selectUserOne(userName);
        if (null == user){
            return null;
        }
        SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(
                user,
                user.getPassword(),
                ByteSource.Util.bytes(user.getSalt()),
                getName());
        return authenticationInfo;
    }
}

3.shiro的配置类

@Configuration
public class ShiroConfig {

    /**
     * 密码匹配凭证管理器(密码加密需要此配置)
     * @return
     */
    @Bean(name = "hashedCredentialsMatcher")
    public HashedCredentialsMatcher hashedCredentialsMatcher() {
        HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
        hashedCredentialsMatcher.setHashAlgorithmName("MD5");
        hashedCredentialsMatcher.setHashIterations(1);// 设置加密次数
        return hashedCredentialsMatcher;
    }

    //配置自定义的Realm
    @Bean
    public MyShiroRealm myShiroRealm(HashedCredentialsMatcher matcher){
        MyShiroRealm myShiroRealm= new MyShiroRealm();
        myShiroRealm.setCredentialsMatcher(matcher);
        return myShiroRealm;
    }

    //将Realm注册到securityManager中
    @Bean
    public DefaultWebSecurityManager securityManager(MyShiroRealm realm){
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        securityManager.setRealm(realm);
        return securityManager;
    }

    //如果没有此name,将会找不到shiroFilter的Bean
    @Bean(name = "shiroFilter")
    public ShiroFilterFactoryBean shiroFilter(org.apache.shiro.mgt.SecurityManager securityManager){
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        shiroFilterFactoryBean.setSecurityManager(securityManager);
        shiroFilterFactoryBean.setLoginUrl("/login");         //表示指定登录页面
        shiroFilterFactoryBean.setSuccessUrl("/user/list");   // 登录成功后要跳转的链接
        shiroFilterFactoryBean.setUnauthorizedUrl("/error");    //未授权页面

        Map<String,String> filterChainDefinitionMap = new LinkedHashMap<>();//拦截器, 配置不会被拦截的链接 顺序判断
        filterChainDefinitionMap.put("/login","anon");                     //所有匿名用户均可访问到Controller层的该方法下
        filterChainDefinitionMap.put("/userLogin","anon");
        filterChainDefinitionMap.put("/image/**","anon");
        filterChainDefinitionMap.put("/css/**", "anon");
        filterChainDefinitionMap.put("/fonts/**","anon");
        filterChainDefinitionMap.put("/js/**","anon");
        filterChainDefinitionMap.put("/logout","logout");
        filterChainDefinitionMap.put("/**", "authc");  //authc:所有url都必须认证通过才可以访问; anon:所有url都都可以匿名访问
        //filterChainDefinitionMap.put("/**", "user");        //user表示配置记住我或认证通过可以访问的地址
        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
        return shiroFilterFactoryBean;
    }

    /**
     * SpringShiroFilter首先注册到spring容器
     * 然后被包装成FilterRegistrationBean
     * 最后通过FilterRegistrationBean注册到servlet容器
     * @return
     */
    @Bean
    public FilterRegistrationBean delegatingFilterProxy(){
        FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
        DelegatingFilterProxy proxy = new DelegatingFilterProxy();
        proxy.setTargetFilterLifecycle(true);
        proxy.setTargetBeanName("shiroFilter");
        filterRegistrationBean.setFilter(proxy);
        return filterRegistrationBean;
    }
    //设置cookie
    @Bean
    public SimpleCookie rememberMeCookie(){
        //这个参数是cookie的名称,对应前端的checkbox的name=rememberMe
        SimpleCookie simpleCookie = new SimpleCookie("rememberMe");
        //记住我cookie生效时间3个小时(单位秒)
        simpleCookie.setMaxAge(10800);
        return simpleCookie;
    }
    //cookie管理对象,记住我功能
    @Bean
    public CookieRememberMeManager rememberMeManager(){
        CookieRememberMeManager cookieRememberMeManager = new CookieRememberMeManager();
        cookieRememberMeManager.setCookie(rememberMeCookie());
        return cookieRememberMeManager;
    }

    //如果没有这两个配置,可能会授权失败,所以依赖中还需要配置aop的依赖
    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(org.apache.shiro.mgt.SecurityManager securityManager) {
        AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
        authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
        return authorizationAttributeSourceAdvisor;
    }
    @Bean
    @ConditionalOnMissingBean
    public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator(){
        DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator=new DefaultAdvisorAutoProxyCreator();
        defaultAdvisorAutoProxyCreator.setProxyTargetClass(true);
        return defaultAdvisorAutoProxyCreator;
    }

    //这里是为了能在html页面引用shiro标签
    @Bean(name = "shiroDialect")
    public ShiroDialect shiroDialect(){
        return new ShiroDialect();
    }

}

4.全局异常处理类

@ControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(ShiroException.class)
    public String doHandleShiroException(ShiroException se, Model model) {
        se.printStackTrace();
        if(se instanceof UnknownAccountException){      //该账号不存在
            return "login";
        }
        if(se instanceof LockedAccountException){       //该账户已被锁定,请联系管理员
            return "login";
        }
        if(se instanceof IncorrectCredentialsException){//密码错误
            return "login";
        }
        if(se instanceof AuthorizationException){       //没有相应权限,请联系管理员
            return "403";
        }else{                                          //登录失败
            return "login";
        }
    }
}

5.LoginController

@Controller
public class LoginController {

    @GetMapping("/login")
    public String login() {
        return "login";
    }

    @PostMapping("/userLogin")
    public String toLogin(String username, String password, Model model){
        UsernamePasswordToken token =new UsernamePasswordToken(username,password);
        Subject subject = SecurityUtils.getSubject();
        try {
            subject.login(token);
            return "redirect:user/list";  
        } catch (UnknownAccountException e) {
            model.addAttribute("msg","该账号不存在");
        } catch (IncorrectCredentialsException e) {
            model.addAttribute("msg","密码错误,请重试");
        } catch (LockedAccountException e) {
            model.addAttribute("msg","该账户已被锁定,请联系管理员");
        } catch (Exception e) {
            model.addAttribute("msg","登录失败");
        }
        return "login";
    }

}

6.权限验证

    @GetMapping("/pageList")
    @ResponseBody
    @RequiresPermissions("user:view")
    public String listPage(){
        return "测试数据!";
    }

7.实现不同的权限显示的页面效果不同

     <div>
        <a shiro:hasPermission="user:add"  href="/toAddUser">添加客户</a>
        <a shiro:hasPermission="user:update"  href="javascript:void(0)">修改客户</a>
        <a shiro:hasPermission="user:delete"  href="javascript:void(0)">删除客户</a>
        <a shiro:hasPermission="user:export"  href="javascript:void(0)">导出客户</a>
    </div>

源码地址: https://gitee.com/ChouHo/learning.git

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值