Shiro入门项目

Shrio初级阶段

一、Springboot与Shiro整合实现用户认证

1.Shiro的核心API

Subject: 用户主体(把操作交给SecurityManager)

SecurityManager:安全管理器(关联Realm)

Realm: Shiro连接数据的桥梁

2.Springboot整合Shiro

2.1 导入Shiro与spring整合依赖

修改pom.xml

 <!-- https://mvnrepository.com/artifact/org.apache.shiro/shiro-spring -->
<dependency>
    <groupId>org.apache.shiro</groupId>
    <artifactId>shiro-spring</artifactId>
    <version>1.5.3</version>
</dependency>
2.2 自定义Realm类
/**
 * 自定义Realm类
 */
public class UserRealm extends AuthorizingRealm {
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        System.out.println("执行授权逻辑");
        return null;
    }

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        System.out.println("执行认证逻辑");
        return null;
    }
}

2.3 书写Shiro配置类

三个方法从上到下关联,用@Bean将其配置到Spring中,提高效率

/**
 * Shiro配置类
 */
@Configuration
public class ShiroConfig {
    /**
     * 1.创建ShiroFilterFactoryBean
     * 2.创建DefaultWebSecurityManager
     * 3.创建Realm
     */

    public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("securityManager") DefaultWebSecurityManager securityManager){
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();

        //设置安全管理器
        shiroFilterFactoryBean.setSecurityManager(securityManager);
        return shiroFilterFactoryBean;
    }

    @Bean(name="securityManager")
    public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("userRealm") UserRealm userRealm){
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        /**
         * 关联realm
         */
        securityManager.setRealm(userRealm);
        return securityManager;
    }

    @Bean(name="userRealm")
    public UserRealm getRealm(){
        return new UserRealm();
    }

}

二、使用Shiro内置过滤器实现页面拦截

1.配置过滤器

​ 将拦截的请求放在Map集合中,在这里有两种写法,一种是将每个请求都put进去,另一种则是将所有的请求put进去,在后者中要注意,比如首页不需要拦截,则需要将其优先级先设定为anon,若在后面设定,则会被覆盖失效。

@Bean
    public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("securityManager") DefaultWebSecurityManager securityManager) {
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        System.out.println("hello");
        //设置安全管理器
        shiroFilterFactoryBean.setSecurityManager(securityManager);
        /**
         * 添加Shiro内置过滤器
         *      常用过滤器:
         *          anon:无需认证(登录)可以访问
         *          authc:必须认证才可以访问
         *          user:如果使用remember me的功能可以直接访问
         *          perms:该资源必须得到角色权限才可以访问
         */
        Map<String, String> filterMap = new LinkedHashMap<>();

        filterMap.put("/user/test","anon");
        //设置拦截的请求
        /*filterMap.put("/user/add","authc");
        filterMap.put("/user/update","authc");*/

        filterMap.put("/user/*","authc");
        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterMap);

        //设置跳转的控制层方法
        shiroFilterFactoryBean.setLoginUrl("/user/login");
        return shiroFilterFactoryBean;
    }

三、完成Controller与页面

1.Controller层完成检查登录方法

利用UsernamePasswordToken带用户名和密码执行登录方法,在subject.login(token)这行代码,会逐步执行ShiroConfig的方法,最后执行UserRealm中的doGetAuthenticationInfo方法,执行认证逻辑。在这里要注意我对两种异常进行了捕获,UnknownAccountException是对未知账户异常进行捕获,IncorrectCredentialsException是对密码错误异常进行捕获,在这里因为是调用的下层方法,所以在后面的UserRealm类中进行说明。

	/**
     * 登录逻辑处理
     */
    @PostMapping("/checkLogin")
    public String checkLogin(String name,String password,Model model){

        /**
         * 利用Shiro编写认证操作
         */
        //获取subject
        Subject subject = SecurityUtils.getSubject();
        //封装用户数据
        UsernamePasswordToken token = new UsernamePasswordToken(name,password);
        //执行登录方法
        try{
            subject.login(token);
            return "redirect:/user/test";
        }catch (UnknownAccountException e){
            //登录失败
            model.addAttribute("info","用户名不存在");
            return "user/login";
        }catch (IncorrectCredentialsException e){
            model.addAttribute("info","密码错误");
            return "user/login";
        }
    }

2.重写UserRealm类

重写UserRealm类中doGetAuthenticationInfo方法,因为是初级阶段,暂时不进行数据库的连接,模拟用户名和密码。首先将Controller层方法中封装的UsernamePasswordToken的对象拿到,然后拿到name和password进行比对。

 @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        System.out.println("执行认证逻辑");
        //Shiro与数据库信息比对
        //假设数据库查出的用户名与密码
        String username = "Ysc666";
        String password = "123456";
        //强转成UsernamePasswordToken
        UsernamePasswordToken token = (UsernamePasswordToken)authenticationToken;
        //进行数据比对
        if(!token.getUsername().equals(username)){
            //用户名不存在
            return null;
        }
        //判断密码
        return new SimpleAuthenticationInfo("",password,"");
    }

3.完成页面的书写

提交信息到后台判断,根据结果跳转页面或弹出警告语句

<h3 th:text="${info}"></h3>
<form action="/user/checkLogin" method="post">
    name :<input type="text" name="name">
    password : <input type="password" name="password">
    <input type="submit" value="submit">
</form>

Shiro实用阶段

一、整合Mybatis

1.导入依赖

使用了druid(阿里提供的数据源)

<!-- https://mvnrepository.com/artifact/com.alibaba/druid -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.1.21</version>
        </dependency>
        <!-- mysql依赖 -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
        <!-- mybatis依赖 -->
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.1.1</version>
        </dependency>
        <!-- lombok依赖 -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>

2.完成相关配置

配置了连接数据库的四个属性以及数据库连接池类型,最后是Mybatis的别名扫描,包扫描。

spring:
  thymeleaf:
    cache: false
  #连接数据库
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/springbootdemo?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Hongkong
    username: root
    password:
    #配置连接池类型 若c3p0就配置c3p0 在这里使用的是阿里的连接池
    type: com.alibaba.druid.pool.DruidDataSource

#配置别名扫描
mybatis:
  type-aliases-package: com.springbootshiro.entity
  mapper-locations: classpath*:/mapper/**Mapper.xml

二、完成基本代码

@Data
public class UserShiro {
    private Integer id;
    private String username;
    private String password;
    private String perms;
}
@Repository
public interface UserShiroMapper {

    @Select("select id,username,password from user_shiro where username=#{name}")
    UserShiro selectByName(@Param("name") String name);

    UserShiro selectById(Integer id);
}
@Service("userShiroService")
public class UserShiroServiceImpl implements UserShiroService {

    @Autowired
    UserShiroMapper userShiroMapper;

    @Override
    public UserShiro selectByName(String name) {
        UserShiro userShiro = userShiroMapper.selectByName(name);
        return userShiro;
    }

    @Override
    public UserShiro selectById(Integer id) {
        UserShiro userShiro = userShiroMapper.selectById(id);
        return userShiro;
    }

}

三、完成授权逻辑

1.重写UserRealm

重写UserRealm中的doGetAuthorizationInfo方法,用后台数据库查询到的perms(权限)进行逻辑操作。首先通过SecurityUtils的方法拿到当前subject,再通过getPrincipal方法拿到当前用户信息,然后查到用户的perms.

@Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        /**
         * 连接数据库
         */
        System.out.println("执行授权逻辑");
        //给资源授权
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        //获取到当前用户
        Subject subject = SecurityUtils.getSubject();
        UserShiro userShiro = (UserShiro)subject.getPrincipal();
        UserShiro user = userShiroService.selectById(userShiro.getId());
        //添加资源的授权字符串
        info.addStringPermission(user.getPerms());
        return info;
    }
 return new SimpleAuthenticationInfo(user,user.getPassword(),"");

2.对拦截逻辑增加授权管理

在ShiroConfig中对需要授权管理增加perms的权限,只有后台查询到的权限满足,才能访问该路径,否则会跳到未授权提示页面

/**
         * 授权过滤器
         * 注意:当前授权拦截后,Shiro会跳转到未授权页面
         */
        filterMap.put("/user/add","perms[add]");
        filterMap.put("/user/udpate","perms[update]");

        filterMap.put("/user/test","anon");
        filterMap.put("/user/checkLogin","anon");
        //设置拦截的请求
        /*filterMap.put("/user/add","authc");
        filterMap.put("/user/update","authc");*/

        filterMap.put("/user/*","authc");
        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterMap);

        //设置跳转的控制层方法
        shiroFilterFactoryBean.setLoginUrl("/user/login");
        //设置未授权提示页面
        shiroFilterFactoryBean.setUnauthorizedUrl("/user/unauth");
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值