springboot整合shiro实现登录验证 - Go语言中文社区

springboot整合shiro实现登录验证


springboot整合shiro实现登录验证

今天第一次接触springboot,本来是要学习springboot和shiro整合的,但是由于springboot结构还不太了解,所以先来了解一下springboot。
springboot可以快速创建一个机遇spring的项目,而且让这个项目跑起来只需要很少的配置就可以了,主要有以下核心功能:
1.独立运行的spring项目:springboot可以以jar包的形式来运行,运行一个springboot项目我们只需要通过jar -jar xx.jar类运行。
2.Spring Boot可以内嵌Tomcat,这样我们无需以war包的形式部署项目。
3.提供starter简化Maven配置:使用Spring或者SpringMVC我们需要添加大量的依赖,而这些依赖很多都是固定的,这里Spring Boot 通过starter能够帮助我们简化Maven配置。
4.自动配置Spring 。
5.准生产的应用监控 。
6.无代码生成和xml配置。
下面就是开始搭建环境了
1、先建一个springboot工程

修改项目group和artifact

选择所需要的依赖

再选择一下工作空间就完成了

idea创建springboot项目自带项目入口,不用自己配置

修改一下入口类,运行就能在浏览器里访问该项目了,注意要在入口类加上一个@RestController的注解

package com.jiang.springboot_shiro;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@SpringBootApplication
public class SpringbootShiroApplication {


    public static void main(String[] args) {
        SpringApplication.run(SpringbootShiroApplication.class, args);
    }
    @RequestMapping(value = "/springboot_shiro",produces = "text/plain;charset=UTF-8")//项目访问URL
    public String index(){
        return "Hello springboot!";
    }
}

现在在浏览器里面输入localhost:8080/springboot_shiro就能看到返回的Hello springboot!

上面这种方式是把入口类作为控制类,如果要将控制器和入口类分离,控制器的包一定要跟启动类是同一目录,如下:

接下来是整合shiro进行认证,代码会在之前的代码上有所改动

pom.xml添加需要的包

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.jiang</groupId>
    <artifactId>springboot_shiro</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>

    <name>springboot_shiro</name>
    <description>Demo project for Spring Boot</description>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.4.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </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>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <version>2.0.3.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.0.18</version>
        </dependency>
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-spring</artifactId>
            <version>1.4.0</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
</dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>


</project>

先建一个user表,在user表中加了一列权限

由于我的是集成了mybatis的,所以要先配置springboot的配置文件

application.properties

#spring集成mybatis环境
mybatis.type-aliases-package=com.jiang.springboot_shiro.entity
#加载mybatis配置文件
mybatis.mapper-locations=classpath:mapper/*.xml
#spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/chun?useUnicode=true&characterEncoding=utf-8
spring.datasource.username=root
spring.datasource.password=

entity.java

package com.jiang.springboot_shiro.entity;

public class User {
    private String name;
    private String password;
    private String authority;

    public void setName(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getPassword() {
        return password;
    }

    public void setAuthority(String authority) {
        this.authority = authority;
    }

    public String getAuthority() {
        return authority;
    }
}

mapper.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="com.jiang.springboot_shiro.mapper.UserMapper">
    <resultMap id="user" type="User">
        <result property="name" column="name"></result>
        <result property="password" column="password"></result>
    </resultMap>
    <select id="findUser" resultType="User" resultMap="user">
        select * from user where name =#{name} and password=#{password}
    </select>

</mapper>

mapper.java

package com.jiang.springboot_shiro.mapper;

import com.jiang.springboot_shiro.entity.User;
import org.apache.ibatis.annotations.Mapper;

@Mapper
public interface UserMapper {
    public User findUser(User user);
}

service.java

package com.jiang.springboot_shiro.service;

import com.jiang.springboot_shiro.entity.User;
import com.jiang.springboot_shiro.mapper.UserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class UserService {
    @Autowired
    private UserMapper userMapper;

    public User findUser(User user){
        return userMapper.findUser(user);
    }
}

controller.java

这里有要注意的地方,在前面搭建springboot框架的时候注释是@RestController,这里要访问页面,要把注释改成@Controller

package com.jiang.springboot_shiro.controller;

import com.jiang.springboot_shiro.entity.User;
import com.jiang.springboot_shiro.service.UserService;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@Controller
public class UserController {
    /*@RequestMapping("springboot_shiro")//项目访问URL
    public String index(){
        return "Hello springboot!";
    }*/
    @Autowired
    private UserService userService;
    @RequestMapping("/")
    public String getIndex(){
        return "login";
    }
    @RequestMapping("all")
    public String getAll(){
        return "all";
    }
    @RequestMapping("one")
    public String getOne(){
        return "one";
    }
    @RequestMapping("login")
    public String login(){
        return "login";
    }
    @RequestMapping("permission")
    public String permission(){
        return "permission";
    }
    @RequestMapping("toLogin")
    public String toLogin(User user, Model model){
        Subject subject=SecurityUtils.getSubject();
        UsernamePasswordToken userToken=new UsernamePasswordToken(user.getName(),user.getPassword());
        try{
            subject.login(userToken);
            return "redirect:/all";
        }catch (UnknownAccountException e){
            model.addAttribute("msg","用户名不存在");
            return "login";
        }catch (IncorrectCredentialsException e){
            model.addAttribute("msg","密码错误");
            return "login";
        }
    }

}

HTML页面就不贴了,只有一个登陆表单,随便写个就行了

最重要的是shiro的配置,这里没有用配置文件,用了注解

shiroConfig.java

package com.jiang.springboot_shiro.shiro;

import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.HashMap;
import java.util.Map;

@Configuration
public class ShiroConfig {
    @Bean(name = "shiroFilterFactoryBean")
    public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("defaultWebSecurityManager")DefaultWebSecurityManager defaultWebSecurityManager){
        ShiroFilterFactoryBean shiroFilterFactoryBean=new ShiroFilterFactoryBean();
        shiroFilterFactoryBean.setSecurityManager(defaultWebSecurityManager);
        Map<String,String> fMap=new HashMap<>();
        //拦截页面
        fMap.put("/all","authc");
        fMap.put("/one","authc");
        //拦截未授权
        fMap.put("/all","perms[user:all]");
        fMap.put("/one","perms[user:one]");
        //被拦截返回登录页面
        shiroFilterFactoryBean.setLoginUrl("/login");
        //授权拦截返回页面
        shiroFilterFactoryBean.setUnauthorizedUrl("/permission");
        shiroFilterFactoryBean.setFilterChainDefinitionMap(fMap);
        return shiroFilterFactoryBean;
    }
    @Bean(name = "defaultWebSecurityManager")
    public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("userRealm")UserRealm userRealm){
        DefaultWebSecurityManager defaultWebSecurityManager=new DefaultWebSecurityManager();
        defaultWebSecurityManager.setRealm(userRealm);
        return defaultWebSecurityManager;
    }
    @Bean(name = "userRealm")
    public UserRealm getUserRealm(){
        return new UserRealm();
    }
}

配置文件里有一些拦截的配置,anon,authc等,这些还有点糊涂。

shiro最重要的还是Realm类,自定义UserRealm需要继承AuthorizingRealm类,并重写其中的doGetAuthenticationInfo方法和doGetAuthorizationInfo方法,其中在controller中调用subject.login(token)时最终是会调用doGetAuthenticationInfo(token)方法,当访问的页面需要鉴权的时候会调用doGetAuthorizationInfo(principle)方法。

我自定义的UserRealm.java

package com.jiang.springboot_shiro.shiro;

import com.jiang.springboot_shiro.entity.User;
import com.jiang.springboot_shiro.service.UserService;
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 org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;

public class UserRealm extends AuthorizingRealm {
    @Autowired
    private UserService userService;
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection arg0){
        System.out.println("授权");
        Subject subject=SecurityUtils.getSubject();
        User user=(User) subject.getPrincipal();
        SimpleAuthorizationInfo simpleAuthorizationInfo=new SimpleAuthorizationInfo();
        simpleAuthorizationInfo.addStringPermission(user.getAuthority());
        return simpleAuthorizationInfo;
    }
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken arg0) throws AuthenticationException {
        // TODO Auto-generated method stub
        System.out.println("认证");

        //shiro判断逻辑
        UsernamePasswordToken user = (UsernamePasswordToken) arg0;
        User realUser = new User();
        realUser.setName(user.getUsername());
        realUser.setPassword(String.copyValueOf(user.getPassword()));
        User newUser = userService.findUser(realUser);
        //System.out.println(user.getUsername());

        if(newUser == null){
            //用户名错误
            //shiro会抛出UnknownAccountException异常
            return null;
        }

        return new SimpleAuthenticationInfo(newUser,newUser.getPassword(),"");
    }

}

这个类还需要改正,因为这个认证的方法里,无论如何都只能返回UnknownAccountException异常,controller中永远都catch不到IncorrectCredentialsException,目前怎么更正我还没想好。

因为没有配置默认 访问路径,只要访问localhost:8080/就能访问该项目了,在我的控制器里面我后来又加上了下面这一段代码,如果没有这一段代码我直接访问返回的是404,但是这样程序已经跑起来了,如果输入localhost:8080/login会发现能够访问的。

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

只是个测试,所以没写首页,直接访问登录页面了。

 

版权声明:本文来源CSDN,感谢博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/c1225992531/article/details/81329558
站方申明:本站部分内容来自社区用户分享,若涉及侵权,请联系站方删除。
  • 发表于 2020-06-28 00:05:13
  • 阅读 ( 656 )
  • 分类:

0 条评论

请先 登录 后评论

官方社群

GO教程

猜你喜欢