11、SpringBoot 集成 Shiro

1、创建项目的环境,添加maven的依赖

<!-- shiro -->
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-spring</artifactId>
            <version>1.4.1</version>
        </dependency>
        <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>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>

2、创建一个 AuthorizingRealm 的子类,用这个类进行两个操作,一个用来授权,一个用来认证

public class UserRealm extends AuthorizingRealm {

    //授权
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        System.out.println("调用授权:=》doGetAuthorizationInfo");
        return null;
    }

    //认证
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        System.out.println("调用认证:=》doGetAuthorizationInfo");
        if (StringUtils.isEmpty(token.getPrincipal())) {
            return null;
        }
        //获取用户信息
        String name = token.getPrincipal().toString();
        String username = "root";
        String password = "123456";
        if (!username.equals(name)) {
            //这里返回后会报出对应异常
            return null;
        } else {
            //这里验证authenticationToken和simpleAuthenticationInfo的信息
            SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(name, password, getName());
            return simpleAuthenticationInfo;
        }
    }
}

3、创建Shiro的核心配置类

@Configuration
public class ShiroConfig {

    @Bean
    public UserRealm userRealm (){
        return new UserRealm();
    }

    @Bean(name = "securityManager")
    public DefaultWebSecurityManager defaultWebSecurityManager(@Qualifier("userRealm") UserRealm userRealm) {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        securityManager.setRealm(userRealm);
        return securityManager;
    }

    @Bean
    public ShiroFilterFactoryBean shiroFilterFactoryBean (@Qualifier("securityManager") DefaultWebSecurityManager defaultWebSecurityManager) {
        ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();
        bean.setSecurityManager(defaultWebSecurityManager);

        Map<String, String> filterMap = new LinkedHashMap<>();
        filterMap.put("/user/**","authc");//需要认证之后才能访问的请求
        bean.setFilterChainDefinitionMap(filterMap);

        //如果没有认证,跳到登入页面
        bean.setLoginUrl("/toLogin");
        bean.setSuccessUrl("/index");
        return bean;
    }
}

4、创建html页面进行简单的测试

<!-- 首页-->
<!
DOCTYPE html> <html lang="en" xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h1>首页</h1> <div th:text="${msg}"></div> <a th:href="@{/user/add}">add</a> | <a th:href="@{user/update}">update</a> </body> </html>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

 <h1>add</h1>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1>update</h1>
</body>
</html>
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

<h1>请登入</h1>
<p th:text="${msg}" style="color: red"></p>
<form action="/login">
    <p>用户名: <input type="text" name="username"/></p>
    <p>密码:<input type="text" name="password"/></p>
    <p><input type="submit"/></p>
</form>
</body>
</html>

5、创建Controller进行页面跳转测试

@Controller
public class IndexController {

    @RequestMapping({"/","/index"})
    public String toIndex(Model model) {
        model.addAttribute("msg","Hello,Shiro");
        return "index";
    }

    @RequestMapping(value = "/user/add")
    public String add () {
        return "user/add";
    }

    @RequestMapping(value = "/user/update")
    public String update () {
        return "user/update";
    }

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

    @RequestMapping(value = "/login")
    public String login (String username, String password,Model model) {
        if(StringUtils.isEmpty(username) || StringUtils.isEmpty(password)) {
            return "请输入用户名和密码!";
        }
        //用户认证信息
        Subject subject = SecurityUtils.getSubject();
        UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken(username,password);
        try {
            //进行验证,这里可以捕获异常,然后返回对应信息
            subject.login(usernamePasswordToken);
//            subject.checkRole("admin");
//            subject.checkPermissions("query", "add");
            return "index";
        } catch (UnknownAccountException e) {
            model.addAttribute("msg","用户名不存在");
            return "login";
        } catch (AuthenticationException e) {
            model.addAttribute("msg","账号或密码错误");
            return "login";
        } catch (AuthorizationException e) {
            model.addAttribute("msg","没有权限");
            return "login";
        }
    }
}

6、创建统一的异常处理

@ControllerAdvice
@Slf4j
public class MyExceptionHandler {

    @ExceptionHandler
    @ResponseBody
    public String ErrorHandler(AuthorizationException e) {
        log.error("没有通过权限验证!", e);
        return "没有通过权限验证!";
    }
}

 

posted @ 2021-06-17 17:04  shunnWcs  阅读(83)  评论(0)    收藏  举报