zoukankan      html  css  js  c++  java
  • SpringBoot与Shiro整合

    修改pom.xml

    <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>

    <!-- 继承Spring Boot的默认父工程 -->

    <!-- Spring Boot 父工程 -->

    <parent>

    <groupId>org.springframework.boot</groupId>

    <artifactId>spring-boot-starter-parent</artifactId>

    <version>1.5.4.RELEASE</version>

    </parent>

    <groupId>com.mxj</groupId>

    <artifactId>springboot-shiro</artifactId>

    <version>0.0.1-SNAPSHOT</version>

    </project>

    1.1. 导入web支持

    修改pom.xml

    <!-- 导入依赖 -->

    <dependencies>

    <!-- 导入web支持:SpringMVC开发支持,Servlet相关的程序 -->

    <!-- web支持,SpringMVC, Servlet支持等 -->

    <dependency>

    <groupId>org.springframework.boot</groupId>

    <artifactId>spring-boot-starter-web</artifactId>

    </dependency>

    </dependencies>

    1.2. 编写测试Controller

    package com.mxj.controller;

    import org.springframework.stereotype.Controller;

    import org.springframework.web.bind.annotation.RequestMapping;

    import org.springframework.web.bind.annotation.ResponseBody;

    @Controller

    public class UserController {

    /**

     * 测试方法

     */

    @RequestMapping("/hello")

    @ResponseBody

    public String hello(){

    System.out.println("UserController.hello()");

    return "ok";

    }

    }

    1.3. 编写SpringBoot启动类

    package com.mxj;

    import org.springframework.boot.SpringApplication;

    import org.springframework.boot.autoconfigure.SpringBootApplication;

    /**

     * SpringBoot启动类

     * @author MA

     *

     */

    @SpringBootApplication

    public class Application {

    public static void main(String[] args) {

    SpringApplication.run(Application.class, args);

    }

    }

    1.4. 导入thymeleaf页面模块

    引入thymeleaf依赖

     

    <!-- 导入thymeleaf依赖 -->

    <dependency>

    <groupId>org.springframework.boot</groupId>

    <artifactId>spring-boot-starter-thymeleaf</artifactId>

    </dependency>

     

    Controller添加测试方法

     

    /**

     * 测试thymeleaf

     */

    @RequestMapping("/testThymeleaf")

    public String testThymeleaf(Model model){

    //把数据存入model

    model.addAttribute("name", "mxj");

    //返回test.html

    return "test";

    }

     

    建立test.html页面

     

    src/main/resource目录下创建templates目录,然后创建test.html页面

     

    <!DOCTYPE html>

    <html>

    <head>

    <meta charset="UTF-8">

    <title>测试Thymeleaf的使用</title>

    </head>

    <body>

    <h3 th:text="${name}"></h3>

    </body>

    </html>

     

    thymeleaf3.0以前对页面标签语法要求比较严格,开始标签必须有对应的结束标签。

     

    如果希望页面语法不严谨,但是也能够运行成功,可以把thymeleaf升级为3.0或以上版本。

     

    升级thymeleaf3.0.2版本:

    <!-- 修改参数 -->

    <properties>

    <!-- 修改JDK的编译版本为1.8 -->

    <java.version>1.8</java.version>

    <!-- 修改thymeleaf的版本 -->

    <thymeleaf.version>3.0.2.RELEASE</thymeleaf.version>

    <thymeleaf-layout-dialect.version>2.0.4</thymeleaf-layout-dialect.version>

    </properties>

    2. Spring BootShiro整合实现用户认证

    2.1. 分析Shiro的核心API

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

    SecurityManager:安全管理器(关联Realm

    RealmShiro连接数据的桥梁

    2.2. Spring Boot整合Shiro

    2.2.1. 导入shirospring整合依赖

    修改pom.xml

    <!-- shiro与spring整合依赖 -->

    <dependency>

    <groupId>org.apache.shiro</groupId>

    <artifactId>shiro-spring</artifactId>

    <version>1.4.0</version>

    </dependency>

    2.2.2. 自定义Realm

    package com.mxj.shiro;

    import org.apache.shiro.authc.AuthenticationException;

    import org.apache.shiro.authc.AuthenticationInfo;

    import org.apache.shiro.authc.AuthenticationToken;

    import org.apache.shiro.authz.AuthorizationInfo;

    import org.apache.shiro.realm.AuthorizingRealm;

    import org.apache.shiro.subject.PrincipalCollection;

    /**

     * 自定义Realm

     * @author MA

     *

     */

    public class UserRealm extends AuthorizingRealm{

    /**

     * 执行授权逻辑

     */

    @Override

    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection arg0) {

    System.out.println("执行授权逻辑");

    return null;

    }

    /**

     * 执行认证逻辑

     */

    @Override

    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken arg0) throws AuthenticationException {

    System.out.println("执行认证逻辑");

    return null;

    }

    }

    2.2.3. 编写Shiro配置类(*

    package com.mxj.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;

    /**

     * Shiro的配置类

     * @author MA

     *

     */

    @Configuration

    public class ShiroConfig {

    /**

     * 创建ShiroFilterFactoryBean

     */

        @Bean

    public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("securityManager")DefaultWebSecurityManager securityManager){

    ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();

    //设置安全管理器

    shiroFilterFactoryBean.setSecurityManager(securityManager);

    return shiroFilterFactoryBean;

    }

    /**

     * 创建DefaultWebSecurityManager

     */

    @Bean(name="securityManager")

    public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("userRealm")UserRealm userRealm){

    DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();

    //关联realm

    securityManager.setRealm(userRealm);

    return securityManager;

    }

    /**

     * 创建Realm

     */

    @Bean(name="userRealm")

    public UserRealm getRealm(){

    return new UserRealm();

    }

    }

    2.3. 使用Shiro内置过滤器实现页面拦截

    package com.mxj.shiro;

    import java.util.LinkedHashMap;

    import java.util.Map;

    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;

    /**

     * Shiro的配置类

     * @author MA

     *

     */

    @Configuration

    public class ShiroConfig {

    /**

     * 创建ShiroFilterFactoryBean

     */

    @Bean

    public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("securityManager")DefaultWebSecurityManager securityManager){

    ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();

    //设置安全管理器

    shiroFilterFactoryBean.setSecurityManager(securityManager);

    //添加Shiro内置过滤器

    /**

     * Shiro内置过滤器,可以实现权限相关的拦截器

     *    常用的过滤器:

     *       anon: 无需认证(登录)可以访问

     *       authc: 必须认证才可以访问

     *       user: 如果使用rememberMe的功能可以直接访问

     *       perms: 该资源必须得到资源权限才可以访问

     *       role: 该资源必须得到角色权限才可以访问

     */

    Map<String,String> filterMap = new LinkedHashMap<String,String>();

    /*filterMap.put("/add", "authc");

    filterMap.put("/update", "authc");*/

    filterMap.put("/testThymeleaf", "anon");

    filterMap.put("/*", "authc");

    //修改调整的登录页面

    shiroFilterFactoryBean.setLoginUrl("/toLogin");

    shiroFilterFactoryBean.setFilterChainDefinitionMap(filterMap);

    return shiroFilterFactoryBean;

    }

    /**

     * 创建DefaultWebSecurityManager

     */

    @Bean(name="securityManager")

    public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("userRealm")UserRealm userRealm){

    DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();

    //关联realm

    securityManager.setRealm(userRealm);

    return securityManager;

    }

    /**

     * 创建Realm

     */

    @Bean(name="userRealm")

    public UserRealm getRealm(){

    return new UserRealm();

    }

    }

    2.4. 实现用户认证(登录)操作

    2.4.1. 设计登录页面

    <!DOCTYPE html>

    <html>

    <head>

    <meta charset="UTF-8">

    <title>登录页面</title>

    </head>

    <body>

    <h3>登录</h3>

    <form method="post" action="login">

    用户名:<input type="text" name="name"/><br/>

    密码:<input type="password" name="password"/><br/>

    <input type="submit" value="登录"/>

    </form>

    </body>

    </html>

    2.4.2. 编写Controller的登录逻辑

    /**

     * 登录逻辑处理

     */

    @RequestMapping("/login")

    public String login(String name,String password,Model model){

    /**

     * 使用Shiro编写认证操作

     */

    //1.获取Subject

    Subject subject = SecurityUtils.getSubject();

    //2.封装用户数据

    UsernamePasswordToken token = new UsernamePasswordToken(name,password);

    //3.执行登录方法

    try {

    subject.login(token);

    //登录成功

    //跳转到test.html

    return "redirect:/testThymeleaf";

    } catch (UnknownAccountException e) {

    //e.printStackTrace();

    //登录失败:用户名不存在

    model.addAttribute("msg", "用户名不存在");

    return "login";

    }catch (IncorrectCredentialsException e) {

    //e.printStackTrace();

    //登录失败:密码错误

    model.addAttribute("msg", "密码错误");

    return "login";

    }

    }

    2.4.3. 编写Realm的判断逻辑

    package com.mxj.shiro;

    import org.apache.shiro.authc.AuthenticationException;

    import org.apache.shiro.authc.AuthenticationInfo;

    import org.apache.shiro.authc.AuthenticationToken;

    import org.apache.shiro.authc.SimpleAuthenticationInfo;

    import org.apache.shiro.authc.UsernamePasswordToken;

    import org.apache.shiro.authz.AuthorizationInfo;

    import org.apache.shiro.realm.AuthorizingRealm;

    import org.apache.shiro.subject.PrincipalCollection;

    /**

     * 自定义Realm

     * @author MA

     *

     */

    public class UserRealm extends AuthorizingRealm{

    /**

     * 执行授权逻辑

     */

    @Override

    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection arg0) {

    System.out.println("执行授权逻辑");

    return null;

    }

    /**

     * 执行认证逻辑

     */

    @Override

    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken arg0) throws AuthenticationException {

    System.out.println("执行认证逻辑");

    //假设数据库的用户名和密码

    String name = "eric";

    String password = "123456";

    //编写shiro判断逻辑,判断用户名和密码

    //1.判断用户名

    UsernamePasswordToken token = (UsernamePasswordToken)arg0;

    if(!token.getUsername().equals(name)){

    //用户名不存在

    return null;//shiro底层会抛出UnKnowAccountException

    }

    //2.判断密码

    return new SimpleAuthenticationInfo("",password,"");

    }

    }

    2.5. 整合MyBatis实现登录

    2.5.1. 导入mybatis相关的依赖

    <!-- 导入mybatis相关的依赖 -->

    <dependency>

    <groupId>com.alibaba</groupId>

    <artifactId>druid</artifactId>

    <version>1.0.9</version>

    </dependency>

    <!-- mysql -->

    <dependency>

    <groupId>mysql</groupId>

    <artifactId>mysql-connector-java</artifactId>

    </dependency>

    <!-- SpringBoot的Mybatis启动器 -->

    <dependency>

    <groupId>org.mybatis.spring.boot</groupId>

    <artifactId>mybatis-spring-boot-starter</artifactId>

    <version>1.1.1</version>

    </dependency>

    2.5.2. 配置application.properties

    位置:src/main/resources目录下

    spring.datasource.driverClassName=com.mysql.jdbc.Driver

    spring.datasource.url=jdbc:mysql://localhost:3306/ssm

    spring.datasource.username=root

    spring.datasource.password=123456

    spring.datasource.type=com.alibaba.druid.pool.DruidDataSource

    mybatis.type-aliases-package=com.mxj.dao

    2.5.3. 编写User实体

    package com.mxj.dao;

    public class User {

    private Integer id;

    private String name;

    private String password;

    public Integer getId() {

    return id;

    }

    public void setId(Integer id) {

    this.id = id;

    }

    public String getName() {

    return name;

    }

    public void setName(String name) {

    this.name = name;

    }

    public String getPassword() {

    return password;

    }

    public void setPassword(String password) {

    this.password = password;

    }

    }

    2.5.4. 编写UserMapper接口

    package com.mxj.mapper;

    import com.itheima.domain.User;

    public interface UserMapper {

    public User findByName(String name);

    }

    2.5.5. 编写UserMapper.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">

    <!-- 该文件存放CRUD的sql语句 -->

    <mapper namespace="com.itheima.mapper.UserMapper">

    <select id="findByName" parameterType="string" resultType="user">

    SELECT id,

    NAME,

    PASSWORD

    FROM

    user where name = #{value}

    </select>

    </mapper>

    2.5.6. 编写业务接口和实现

    接口:

    package com.mxj.service;

    import com.itheima.domain.User;

    public interface UserService {

    public User findByName(String name);

    }

    实现;

    package com.mxj.service.impl;

    import org.springframework.beans.factory.annotation.Autowired;

    import org.springframework.stereotype.Service;

    import com.itheima.domain.User;

    import com.itheima.mapper.UserMapper;

    import com.itheima.service.UserService;

    @Service

    public class UserServiceImpl implements UserService{

    //注入Mapper接口

    @Autowired

    private UserMapper userMapper;

    @Override

    public User findByName(String name) {

    return userMapper.findByName(name);

    }

    }

    2.5.7. 添加@MapperScan注解

    package com.mxj;

    import org.mybatis.spring.annotation.MapperScan;

    import org.springframework.boot.SpringApplication;

    import org.springframework.boot.autoconfigure.SpringBootApplication;

    /**

     * SpringBoot启动类

     * @author MA

     *

     */

    @SpringBootApplication

    @MapperScan("com.mxj.mapper")

    public class Application {

    public static void main(String[] args) {

    SpringApplication.run(Application.class, args);

    }

    }

    2.5.8. 修改UserRealm

    package com.mxj.shiro;

    import org.apache.shiro.authc.AuthenticationException;

    import org.apache.shiro.authc.AuthenticationInfo;

    import org.apache.shiro.authc.AuthenticationToken;

    import org.apache.shiro.authc.SimpleAuthenticationInfo;

    import org.apache.shiro.authc.UsernamePasswordToken;

    import org.apache.shiro.authz.AuthorizationInfo;

    import org.apache.shiro.realm.AuthorizingRealm;

    import org.apache.shiro.subject.PrincipalCollection;

    import org.springframework.beans.factory.annotation.Autowired;

    import com.mxj.dao.User;

    import com.mxj.service.UserService;

    /**

     * 自定义Realm

     * @author MA

     *

     */

    public class UserRealm extends AuthorizingRealm{

    /**

     * 执行授权逻辑

     */

    @Override

    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection arg0) {

    System.out.println("执行授权逻辑");

    return null;

    }

    @Autowired

    private UserService userSerivce;

    /**

     * 执行认证逻辑

     */

    @Override

    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken arg0) throws AuthenticationException {

    System.out.println("执行认证逻辑");

    //编写shiro判断逻辑,判断用户名和密码

    //1.判断用户名

    UsernamePasswordToken token = (UsernamePasswordToken)arg0;

    User user = userSerivce.findByName(token.getUsername());

    if(user==null){

    //用户名不存在

    return null;//shiro底层会抛出UnKnowAccountException

    }

    //2.判断密码

    return new SimpleAuthenticationInfo("user.getName()",user.getPassword(),"");

    }

    }

    3. Spring BootShiro整合实现用户授权

    3.1. 使用Shiro内置过滤器拦截资源

    /**

     * 创建ShiroFilterFactoryBean

     */

    @Bean

    public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("securityManager")DefaultWebSecurityManager securityManager){

    ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();

    //设置安全管理器

    shiroFilterFactoryBean.setSecurityManager(securityManager);

    //添加Shiro内置过滤器

    /**

     * Shiro内置过滤器,可以实现权限相关的拦截器

     *    常用的过滤器:

     *       anon: 无需认证(登录)可以访问

     *       authc: 必须认证才可以访问

     *       user: 如果使用rememberMe的功能可以直接访问

     *       perms: 该资源必须得到资源权限才可以访问

     *       role: 该资源必须得到角色权限才可以访问

     */

    Map<String,String> filterMap = new LinkedHashMap<String,String>();

    /*filterMap.put("/add", "authc");

    filterMap.put("/update", "authc");*/

    filterMap.put("/testThymeleaf", "anon");

    //放行login.html页面

    filterMap.put("/login", "anon");

    //授权过滤器

    //注意:当前授权拦截后,shiro会自动跳转到未授权页面

    filterMap.put("/add", "perms[user:add]");

    filterMap.put("/*", "authc");

    //修改调整的登录页面

    shiroFilterFactoryBean.setLoginUrl("/toLogin");

    //设置未授权提示页面

    shiroFilterFactoryBean.setUnauthorizedUrl("/noAuth");

    shiroFilterFactoryBean.setFilterChainDefinitionMap(filterMap);

    return shiroFilterFactoryBean;

    }

    3.2. 完成Shiro的资源授权

    UserRealm

    /**
    * 执行授权逻辑
    * @param principals
    * @return
    */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {

    System.out.println("执行授权逻辑");
    //给资源进行授权
    SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();

    //添加资源的授权字符串
    //info.addStringPermission("user:add");

    //到数据库查询当前用户的授权字符串
    //获取当前登陆用户
    Subject subject = SecurityUtils.getSubject();
    String name= (String) subject.getPrincipal();
    User user = userService.findByName(name);

    info.addStringPermission(user.getPerms());
    return info;
    }

    4.  thymeleafshiro标签整合使用

    4.1. 导入thymeleaf扩展坐标

    <!-- thymelshiro的扩展坐标 -->

    <dependency>

    <groupId>com.github.theborakompanioni</groupId>

    <artifactId>thymeleaf-extras-shiro</artifactId>

    <version>2.0.0</version>

    </dependency>

    4.2. 配置ShiroDialect

    ShiroConfig类里面添加getShiroDialect方法

    /**

     * 配置ShiroDialect,用于thymeleafshiro标签配合使用

     */

    @Bean

    public ShiroDialect getShiroDialect(){

    return new ShiroDialect();

    }

    4.3. 在页面上使用shiro标签

    <!DOCTYPE html>

    <html>

    <head>

    <meta charset="UTF-8">

    <title>测试Thymeleaf的使用</title>

    </head>

    <body>

    <h3 th:text="${name}"></h3>

    <hr/>

    <div shiro:hasPermission="user:add">

    进入用户添加功能: <a href="add">用户添加</a><br/>

    </div>

    <div shiro:hasPermission="user:update">

    进入用户更新功能: <a href="update">用户更新</a><br/>

    </div>

    <a href="toLogin">登录</a>

    </body>

    </html>

  • 相关阅读:
    C++成员变量与函数内存分配
    Sqlite ContentProvider Loader 上下文 对话框
    好书好人生--读书的步骤
    小智慧40
    流媒体开发之-直播界面切换电视台频道
    HDU 4617Weapon(两条异面直线的距离)
    BON取代半岛电视,美国人要“换口味”了吗?
    【Todo】Lucene系统学习
    Zookeeper学习 & Paxos
    C++中的虚继承 & 重载隐藏覆盖的讨论
  • 原文地址:https://www.cnblogs.com/mxj961116/p/11337391.html
Copyright © 2011-2022 走看看