Spring boot开发总结四(整合shiro)

1. shiro的简单配置

      1.1 pom坐标

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

     1.2 用户验证与授权

package com.zp.shirodemo.config;
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.subject.PrincipalCollection;
import java.util.HashSet;
import java.util.Set;
/**
 * @ClassName Realm
 */
public class CustomRealm extends AuthorizingRealm {
    /**
     * 获取身份验证信息
     * Shiro中,最终是通过 Realm 来获取应用程序中的用户、角色及权限信息的。
     * @param authenticationToken 用户身份信息 token
     * @return 返回封装了用户信息的 AuthenticationInfo 实例
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        System.out.println("————身份认证方法————");
        UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;
        String username = token.getUsername();
        //通过用户名获取 用户信息
        UserBean userBean=new UserBean("1",username, "123456");
        if (null == userBean) {
            //用户不存在,抛出UnknownAccountException异常
            throw new UnknownAccountException();
        } else{
            //用户纯在进行验证
            return  new SimpleAuthenticationInfo(userBean,userBean.getPassword(),ByteSource.Util.bytes(userBean.getName()+"salt"),getName());
        }
    }
    /**
     * 获取授权信息
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        System.out.println("————权限认证————");
        UserBean username = (UserBean) SecurityUtils.getSubject().getPrincipal();
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        //获得该用户角色,权限,可从数据库中查出
        info.setRoles(Set<String> roles);
        info.setStringPermissions(Set<String> permissions);
        return info;
    }

}

     1.3 shiro相关配置

package com.zp.shirodemo.config;
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.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;
import org.springframework.web.servlet.handler.SimpleMappingExceptionResolver;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Properties;
@Configuration
public class ShiroConfig {
    @Bean
    public ShiroFilterFactoryBean shirFilter(SecurityManager securityManager) {
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        // 必须设置 SecurityManager
        shiroFilterFactoryBean.setSecurityManager(securityManager);
        // setLoginUrl 如果不设置值,默认会自动寻找Web工程根目录下的"/login.jsp"页面 或 "/login" 映射
        shiroFilterFactoryBean.setLoginUrl("/main/toLogin");
        // 设置无权限时跳转的 url;
        shiroFilterFactoryBean.setUnauthorizedUrl("/main/403");
        // 设置拦截器
        Map<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
        //游客,开发权限
        filterChainDefinitionMap.put("/main/guest/**", "anon");
//        //用户,需要角色权限 “user”
//        filterChainDefinitionMap.put("/main/user/**", "roles[user]");
//        //管理员,需要角色权限 “admin”
//        filterChainDefinitionMap.put("/main/admin/**", "roles[admin]");
        //开放登陆接口
        filterChainDefinitionMap.put("/main/toLogin", "anon");
        //开放登陆接口
        filterChainDefinitionMap.put("/main/login", "anon");
        //其余接口一律拦截
        //主要这行代码必须放在所有权限设置的最后,不然会导致所有 url 都被拦截
        filterChainDefinitionMap.put("/**", "authc");
        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
        System.out.println("Shiro拦截器工厂类注入成功");
        return shiroFilterFactoryBean;
    }

    /**
     * 注入 securityManager
     */
    @Bean
    public SecurityManager securityManager() {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        // 设置realm.
        securityManager.setRealm(customRealm());
        return securityManager;
    }
  
    /**
     * 自定义身份认证 realm;
     * <p>
     * 必须写这个类,并加上 @Bean 注解,目的是注入 CustomRealm,
     * 否则会影响 CustomRealm类 中其他类的依赖注入
     */
    @Bean
    public CustomRealm customRealm() {
        return new CustomRealm();
    }
}

anon:例子/admins/**=anon  表示可以匿名使用,不需要验证及授权就可访问

authc:例如/user/**=authc  表示需要认证(登录)才能使用

user:例如/user/**=user  表示必须存在用户, 身份认证通过或通过记住我认证通过的可以访问,当登入操作时不做检查

authcBasic:例如/user/**=authcBasic  表示httpBasic认证

roles:例子/user/**=/user/**=roles["admin,guest"], 设置角色,单个参数可省略引号,,每个参数通过才算通过

perms:例子/user/**=perms["add:*,mod:*"],设置权限,单个参数可省略引号,当有多个参数时必须每个参数都通过才通过。

rest:例子/admins/user/**=rest[user],根据请求的方法,相当于/admins/user/**=perms[user:method] ,其中method为post,get,delete等。

port:例子/admins/user/**=port[8081],当请求的url的端口不是8081是跳转到schemal://serverName:8081?queryString,其中schmal是协议http或https等,serverName是你访问的host,8081是url配置里port的端口,queryString是你访问的url里的?后面的参数。

ssl:例子/admins/user/**=ssl 表示安全的url请求,协议为https

注:

anon,authcBasic,auchc,user是认证过滤器,

perms,roles,ssl,rest,port是授权过滤器

     1.4 登录接口

  @RequestMapping("/login")
    public String login(Model model, HttpServletRequest request, HttpServletResponse response){
        response.setHeader("root", request.getContextPath());
        String userName = request.getParameter("username");
        String password = request.getParameter("password");
        // 1.获取Subject
        Subject subject = SecurityUtils.getSubject();
        // 2.封装用户数据
        UsernamePasswordToken token = new UsernamePasswordToken(userName, password);
        // 3.执行登录方法
        try{
        //有记住功能的可通过setRememberMe设置
        //token.setRememberMe(true);
        //登录并定向到首页
            subject.login(token);
            return "redirect:/main/toIndex";
        } catch (UnknownAccountException e){
            e.printStackTrace();
            request.setAttribute("msg","用户名/密码错误");
            return "login";
        } catch (IncorrectCredentialsException e){
            request.setAttribute("msg","用户名/密码错误");
            return "login";
        }
    }

     1.5 退出接口

  @RequestMapping("/logout")
    public String logout(){
        Subject subject = SecurityUtils.getSubject();
        if (subject != null) {
            subject.logout();
        }
        return "redirect:/login";
    }

2. shiro的其他配置

    2.1 注解整合

 /**
     * 开启Shiro的注解
     * @return
     */
    @Bean
    @DependsOn({"lifecycleBeanPostProcessor"})
    public DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator(){
        DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
        advisorAutoProxyCreator.setProxyTargetClass(true);
        return advisorAutoProxyCreator;
    }
    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(){
        AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
        authorizationAttributeSourceAdvisor.setSecurityManager(securityManager());
        return authorizationAttributeSourceAdvisor;
    }
    @Bean
    public LifecycleBeanPostProcessor lifecycleBeanPostProcessor(){
        return new LifecycleBeanPostProcessor();
    }
/**
 * @Description //权限注解无权限时的视图配置
 **/
    @Bean
    public SimpleMappingExceptionResolver simpleMappingExceptionResolver(){
        SimpleMappingExceptionResolver simpleMappingExceptionResolver=new     SimpleMappingExceptionResolver();
        Properties properties=new Properties();
        properties.put("org.apache.shiro.authz.UnauthorizedException","/main/403");
        simpleMappingExceptionResolver.setExceptionMappings(properties);
        return simpleMappingExceptionResolver;
    }

    2.2 jsp整合

页面引入

<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>

    2.3 freemarker整合

引用pom坐标:

         <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-freemarker</artifactId>
        </dependency>
        <dependency>
            <groupId>net.mingsoft</groupId>
            <artifactId>shiro-freemarker-tags</artifactId>
            <version>0.1</version>
        </dependency>

 添加配置bean :

/**
*添加了这个bean后,在application.properties中的配置会失效,默认配置也会失效
**/
@Bean
    public FreeMarkerConfigurer freeMarkerConfigurer() throws IOException, TemplateException {
        FreeMarkerConfigurer freeMarkerConfigurer = new FreeMarkerConfigurer();
        freeMarkerConfigurer.setTemplateLoaderPath("classpath:templates/");
        freemarker.template.Configuration configuration = freeMarkerConfigurer.createConfiguration();
        configuration.setDefaultEncoding("UTF-8");
        //这里可以添加其他共享变量 比如sso登录地址
        configuration.setSharedVariable("shiro", new ShiroTags());
        freeMarkerConfigurer.setConfiguration(configuration);
        return freeMarkerConfigurer;
    }

 模板中应用:

  • <@shiro.principal property="name" />   输出当前用户信息,通常为登录帐号信息 
  • <@shiro.guest>  </@shiro.guest> 未认证(包含未记住)的用户
  • <@shiro.user> </@shiro.user> 认证通过或已记住的用户 
  • <@shiro.authenticated></@shiro.authenticated>  已认证通过的用户。不包含已记住的用户
  • <@shiro.notAuthenticated></@shiro.notAuthenticated>   未认证通过的用户。与authenticated标签相对
  • <@shiro.hasRole name=”admin”></@shiro.hasRole>  验证当前用户是否属于该角色
  • <@shiro.hasAnyRoles name="admin,user"></@shiro.hasAnyRoles>验证当前用户是否属于这些角色中的任何一个
  • <@shiro.hasPermission name="/order:*"></@shiro.hasPermission> 验证当前用户是否拥有该权限
  • <@shiro.lacksRole name="admin"></@shiro.lacksRole>  验证当前用户不属于该角色
  • <@shiro.lacksPermission name="/order:*"></@shiro.lacksPermission> 验证当前用户不拥有某种权限

    2.4 thymeleaf整合

引用pom坐标及规定版本:

       <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
        <dependency>
            <groupId>com.github.theborakompanioni</groupId>
            <artifactId>thymeleaf-extras-shiro</artifactId>
            <version>2.0.0</version>
        </dependency>
        <!--放在dependencies标签外-->
        <properties>
            <java.version>1.8</java.version>
            <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
            <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
            <java.version>1.8</java.version>
            <thymeleaf.version>3.0.0.RELEASE</thymeleaf.version>
            <thymeleaf-layout-dialect.version>2.0.0</thymeleaf-layout-dialect.version>
        </properties>

配置文件

#指定模板所在的目录
spring.thymeleaf.prefix= classpath:/templates/
#检查模板路径是否存在
spring.thymeleaf.check-template-location= true
#是否缓存,开发模式下设置为false,避免改了模板还要重启服务器,线上设置为true,可以提高性能。
spring.thymeleaf.cache= false
spring.thymeleaf.suffix= .html
#与Servlet中设置输出对应属性效果一致。
spring.thymeleaf.encoding= UTF-8
spring.thymeleaf.content-type= text/html
spring.thymeleaf.mode= HTML5

添加配置bean

 @Bean(name = "shiroDialect")
    public ShiroDialect shiroDialect() {
        return new ShiroDialect();
    }

模板中应用:

引入   <html lang="en" xmlns:th="http://www.thymeleaf.org" xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">

应用在要控制显示的标签中:例如:<a shiro:hasPermission="add" href="#">新增</a>

控制详解:

  • shiro:guest=""   验证当前用户是否为“访客”,即未认证(包含未记住)的用户。
  • shiro:user=""    认证通过或已记住的用户
  • shiro:authenticated=""   已认证通过的用户。不包含已记住的用户,这是与user标签的区别所在。
  • shiro:notAuthenticated=""   未认证通过用户,与authenticated相对应。与guest的区别是,该含已记住用户。
  • shiro:hasRole="admin"  验证当前用户是否属于该角色。
  • shiro:lacksRole="developer"   与hasRole标签逻辑相反,当用户不属于该角色时验证通过。
  • shiro:hasAllRoles="developer, 2"   验证当前用户是否属于以下所有角色。
  •  shiro:hasAnyRoles="admin, vip, developer,1"   验证当前用户是否属于以下任意一个角色。
  • shiro:hasPermission="userInfo:add"   验证当前用户是否拥有指定权限。
  • shiro:hasAllPermissions="userInfo:view, userInfo:add"   验证当前用户是否拥有以下所有角色。
  • shiro:hasAnyPermissions="userInfo:view, userInfo:del"  验证当前用户是否拥有以下任意一个权限。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

郑重其事,鹏程万里

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值