spring boot整合Shiro实现单点登录的示例代码

下面是关于“spring boot整合Shiro实现单点登录的示例代码”的详细攻略。

下面是关于“spring boot整合Shiro实现单点登录的示例代码”的详细攻略。

环境准备

首先,我们需要准备以下环境:

  • JDK 8
  • Maven
  • IDE:Eclipse 或者 Intellij IDEA

在环境准备完成后,我们接下来需要进行以下的准备工作。

创建Spring Boot工程

我们可以通过Maven快速构建一个Spring Boot应用程序,然后加上Shiro依赖即可。

  1. 打开Eclipse或者Intellij IDEA,创建一个普通的Maven工程;
  2. 在pom.xml文件中添加以下的Spring Boot依赖:
<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
   <groupId>org.apache.shiro</groupId>
   <artifactId>shiro-spring</artifactId>
   <version>1.4.0</version>
</dependency>
  1. 执行命令 mvn clean install 完成依赖的下载

Shiro基本配置

接下来,我们需要进行Shiro的基本配置

  1. 创建ShiroConfig类

在src/main/java下创建一个ShiroConfig类

@Configuration
public class ShiroConfig {
    /**
     * 配置Shiro到Spring容器
     * @param securityManager
     * @return
     */
    @Bean(name = "shiroFilter")
    protected ShiroFilterFactoryBean shiroFilterFactoryBean(DefaultWebSecurityManager securityManager) {
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        //声明securityManager
        shiroFilterFactoryBean.setSecurityManager(securityManager);
        //注册authcFilter过滤器
        Map<String, Filter> filters = new LinkedHashMap<>();
        filters.put("authc", authcFilter());
        shiroFilterFactoryBean.setFilters(filters);

        //为URL设置访问所需要的角色
        Map<String, String> filterChainDefinitionMap = new LinkedHashMap<String, String>();
        filterChainDefinitionMap.put("/logout", "logout");
        filterChainDefinitionMap.put("/login", "authc");
        filterChainDefinitionMap.put("/**", "authc");
        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
        shiroFilterFactoryBean.setLoginUrl("/login");

        return shiroFilterFactoryBean;
    }

    /**
     * 创建securityManager
     *
     * @return
     */
    @Bean(name = "securityManager")
    protected DefaultWebSecurityManager defaultWebSecurityManager(UserRealm bean) {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        //注入Realm
        securityManager.setRealm(bean);
        return securityManager;
    }

    /**
     * 创建Realm
     *
     * @return
     */
    @Bean(name = "realm")
    public UserRealm userRealm() {
        return new UserRealm();
    }

    /**
     * 注册authcFilter过滤器
     * @return
     */
    @Bean(name = "authc")
    public AuthenticationFilter authcFilter() {
        UsernamePasswordAuthenticationFilter authcFilter = new UsernamePasswordAuthenticationFilter();
        authcFilter.setLoginUrl("/login");
        return authcFilter;
    }
}
  1. 创建一个UserRealm类

在src/main/java下创建一个UserRealm类:

public class UserRealm extends AuthorizingRealm {
    @Autowired
    private UserService userService;

    /**
     * 授权
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
        User user = (User) principalCollection.getPrimaryPrincipal();

        //获取角色ResouceCode关联信息
        List<ResouceCode> resouceCodeList = userService.selectResourceCodeList(user.getUserName());
        //将role和url加入到授权对象中
        if (resouceCodeList != null && resouceCodeList.size() > 0) {
            for (ResouceCode resouceCode : resouceCodeList) {
                authorizationInfo.addRole(resouceCode.getRoleCode().toUpperCase());
                authorizationInfo.addStringPermission(resouceCode.getResCode().toLowerCase());
            }
        }

        return authorizationInfo;
    }

    /**
     * 验证 登录
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        UsernamePasswordToken usernamePasswordToken = (UsernamePasswordToken) authenticationToken;
        String username = usernamePasswordToken.getUsername();
        if (StringUtils.isBlank(username)) {
            return null;
        }

        User user = userService.selectUserByUserName(username);
        if (user == null) {
            return null;
        }
        SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(user, user.getPassword(), ByteSource.Util.bytes(user.getCredentialsSalt()), getName());

        return authenticationInfo;
    }
}

编写Controller和View

接下来,我们需要编写Controller和View

  1. 添加登录页面

在src/main/resources下创建login.html页面:

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>登陆</title>
</head>
<body>
<div>
<form method="post" th:action="@{/login}">
<div>
<label>用户名: <input type="text" name="username" required></label>
</div>
<div>
<label>密码: <input type="password" name="password" required></label>
</div>
<div><input type="submit" value="登陆"></div>
</form>
</div>
</body>
</html>
  1. 创建HomeController类

在src/main/java下创建一个HomeController类,实现登录成功后的跳转:

@Controller
public class HomeController {

    /**
     * 登录成功后跳转到主页面
     *
     * @return
     */
    @RequestMapping("/home")
    public String home() {
        return "/views/home";
    }
}
  1. 创建IndexController类

在src/main/java下创建一个IndexController类,实现登录和退出:

@Controller
public class IndexController {

    /**
     * 登录
     *
     * @return
     */
    @RequestMapping("/login")
    public String login() {
        return "/views/login";
    }

    /**
     * 退出
     *
     * @return
     */
    @RequestMapping("/logout")
    public String logout() {
        SecurityUtils.getSubject().logout();
        return "redirect:/login";
    }
}
  1. 创建Home页面

在src/main/resources/views下创建一个home.html页面,实现登录验证后的统一页面:

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>首页</title>
</head>
<body>
<h1>欢迎访问首页</h1>
</body>
</html>

两个示例说明

下面我们演示两个Shiro单点登录的应用:

示例一:普通登录

  1. 在浏览器中输入网址 http://localhost:8080/login,会跳转到登录页面;
  2. 在登录页面中输入用户名和密码,点击“登陆”,会跳转到应用的首页:http://localhost:8080/home,同时在请求头中设置了Cookie;
  3. 访问 http://localhost:8080/home,会发现并没有被拦截,说明登录成功;

示例二:多个应用的单点登录

假设有两个应用APP1和APP2,在浏览器中访问APP1,然后跳转到APP2,由于已经实现了Shiro单点登录,所以在访问APP2时,就无需再次输入用户名和密码。

  1. 访问APP1,执行登录操作,成功登录;
  2. 在APP1的页面上添加访问APP2页面的链接,并设置URL为APP2的登录页面URL;
  3. 点击APP2的链接,跳转到APP2的登录页面,此时我们并不需要再次输入用户名和密码;
  4. 点击APP2的首页链接,会发现并没有被拦截,说明登录成功。

总结

至此,我们已经完成了Spring Boot整合Shiro实现单点登录的示例代码。需要注意的是,这里的示例是最基本的示例,如果想要在实际应用中使用,还需要根据实际情况进行具体的配置和开发。

本文标题为:spring boot整合Shiro实现单点登录的示例代码

基础教程推荐