Spring Boot 整合Shiro安全认证框架

Apache Shiro是一个开源的轻量级的java安全框架,它提供身份验证,授权,密码管理以及会话管理功能等。相对于SpringSecurity,Shiro框架跟家直观,易用,同时也能提供健壮的安全性,在传统SSM框架中,手动配置Shiro的步骤还是比较多的,针对Springboot,shiro官方提供了shiro-spring-boot-web-starter 的使用步骤。

整合Shiro

1.加依赖pom.xml

   <!--安全认证  shiro-->
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-spring-boot-web-starter</artifactId>
            <version>1.4.0</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/com.github.theborakompanioni/thymeleaf-extras-shiro -->
        <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-starter-thymeleaf</artifactId>
            <version>2.1.3.RELEASE</version>
        </dependency>
        <!--webMvc-->
        <!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>5.1.5.RELEASE</version>
        </dependency>

2.配置shiro文件,application.yml

server:
  port: 8808

  #安全认证  shiro
shiro:
  enabled: true               #开启shiro默认true
  web:
    enabled: true             #开启shiro web 默认true
  loginUrl: /login              #登录地址 、默认/login.jsp
  successUrl: /index            #登录成功地址.默认/
  unauthorizedUrl: /unauthorized    #为授权默认跳转的地址
  sessionManager:
    sessionIdCookieEnabled: true  #是否允许Cookie 实现绘画跟踪,默认为true
    sessionIdUrlRewritingEnabled: true

spring:
  thymeleaf:
    prefix: classpath:/templates/
    servlet:
      content-type: text/html
    suffix: .html
    encoding: utf-8
    cache: false
    mode: LEGACYHTML5

3.配置类,提供两个Bean即可,这里配置了两个用户,sang/123,admin/123分别对应角色user&admin,user具有read权限,admin具有read,write权限。

package com.example.demo.config;

import at.pollux.thymeleaf.shiro.dialect.ShiroDialect;
import org.apache.shiro.realm.Realm;
import org.apache.shiro.realm.text.TextConfigurationRealm;
import org.apache.shiro.spring.web.config.DefaultShiroFilterChainDefinition;
import org.apache.shiro.spring.web.config.ShiroFilterChainDefinition;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class ShiroConfig {

    @Bean
    public Realm realm(){
        TextConfigurationRealm realm = new TextConfigurationRealm();
        realm.setUserDefinitions("sang=123,user\n admin=123,admin");
        realm.setRoleDefinitions("admin=read,write\n user=read");
        return realm;
    }

    @Bean
    public ShiroFilterChainDefinition shiroFilterChainDefinition(){
        DefaultShiroFilterChainDefinition chainDefinition = new DefaultShiroFilterChainDefinition();
        chainDefinition.addPathDefinition("/login","anon");
        chainDefinition.addPathDefinition("/doLogin","anon");
        chainDefinition.addPathDefinition("/logout","logout");
        chainDefinition.addPathDefinition("/**","authc");
        return chainDefinition;
    }
    @Bean
    public ShiroDialect shiroDialect(){
        return new ShiroDialect();
    }

}

4.编写接口controller.java

package com.example.demo.controller;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authz.annotation.Logical;
import org.apache.shiro.authz.annotation.RequiresRoles;
import org.apache.shiro.subject.Subject;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class UserController {

    @RequestMapping("/doLogin")
    public String doLogin(String username, String password, Model model){
        UsernamePasswordToken token= new UsernamePasswordToken(username,password);
        Subject subject = SecurityUtils.getSubject();
        try {
            subject.login(token);
        } catch (AuthenticationException e) {
            e.printStackTrace();
            model.addAttribute("error", "用户名或密码输入错误");
            return "login";
        }
        return "redirect:/index";
    }


    @RequiresRoles("/admin")
    @GetMapping("/admin")
    public String admin(){

        return "admin";
    }

    @RequiresRoles(value = {"admin","user"},logical = Logical.OR)
    @GetMapping("/user")
    public String user(){
        return "user";
    }

}

5.配置不需要角色就能访问的接口

package com.example.demo.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class WebMvcConfig implements WebMvcConfigurer {

    @Override
    public void addViewControllers(ViewControllerRegistry registrt){
        registrt.addViewController("/login").setViewName("login");
        registrt.addViewController("/index").setViewName("index");
        registrt.addViewController("/unauthorized").setViewName("unauthorized");

    }

}

6.编写全局异常处理器进行全局异常处理

package com.example.demo.config;

import org.apache.shiro.authz.AuthorizationException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.servlet.ModelAndView;

@ControllerAdvice
public class ExceptionController {

    @ExceptionHandler(AuthorizationException.class)
    public ModelAndView error(AuthorizationException e){
        ModelAndView mv = new ModelAndView("unauthorized");
        mv.addObject("error",e.getMessage());
        return mv;
    }

}

7.编写5个前端页面resources/templates

index.html

<!DOCTYPE html>
<html lang="en" xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h2>Hello,<shiro:principal/></h2>
<h2><a href="/logout">注销登录</a> </h2>
<h2><a shiro:hasRole="admin" href="/admin" >管理员页面</a></h2>
<h2><a shiro:hasAnyRoles="admin,user" href="/user" >普通用户页面</a></h2>
<h2><a shiro:hasAllRoles="admin" href="/admin">CYC</a></h2>
</body>
</html>

login.html

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaaf.org">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div>
    <form action="/doLogin" method="post">
        <input type="text" name="username"><br/>
        <input type="password" name="password"><br/>
        <div th:text="${error}"></div>
        <input type="submit" value="登录"/>
    </form>
</div>
</body>
</html>

user.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body><h1>普通用户页面</h1>
</body>
</html>

admin.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1>管理员页面</h1>
</body>
</html>

unauthorized.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>
    <!--/*@thymesVar id="error" type="aj"*/-->
    <h1 th:text="${error}"></h1>
</div>
</body>
</html>

8.启动项目,访问localhost:8808/login-----------------------分别使用sang / 123   &   admin / 123 登录

如果你以user登录,然后在地址栏中访问admin结果为不能访问

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值