SpringBoot整合Shiro的方法详解(springboot整合shiro和redis)

网友投稿 266 2022-08-07


SpringBoot整合Shiro的方法详解(springboot整合shiro和redis)

目录1.Shito简介1.1 什么是shiro1.2 有哪些功能2.QuickStart3.SpringBoot中集成1.导入shiro相关依赖2.自定义UserRealm3.定义shiroConfig4.新建页面进行测试

1.Shito简介

1.1 什么是shiro

Apache Shiro是一个java安全(权限)框架

Shiro可以非常容易的开发出足够好的应用,其不仅可以用在javase环境,也可以用在javaee环境

shiro可以完成,认证,授权,加密,会话管理,web集成,缓存等。

下载地址:http://shiro.apache.org/

1.2 有哪些功能

2.QuickStart

Git下载地址

官网下载的可能慢一些

首先新建一个普通的maven项目,然后在项目中导入新的maven项目模块,结构如下:

然后开始创建我们需要的文件,这些文件都可以在官网下载的文件中可以找到:

shiro.ini:

# Users and their assigned roles

#

# Each line conforms to the format defined in the

# org.apache.shiro.realm.text.TextConfigurationRealm#setUserDefinitions JavaDoc

# -----------------------------------------------------------------------------

[users]

# user 'root' with password 'secret' and the 'admin' role

root = secret, admin

# user 'guest' with the password 'guest' and the 'guest' role

guest = guest, guest

# user 'presidentskroob' with password '12345' ("That's the same combination on

# my luggage!!!" ;)), and role 'president'

presidentskroob = 12345, president

# user 'darkhelmet' with password 'ludicrousspeed' and roles 'darklord' and 'schwartz'

darkhelmet = ludicrousspeed, darklord, schwartz

# user 'lonestarr' with password 'vespa' and roles 'goodguy' and 'schwartz'

lonestarr = vespa, goodguy, schwartz

# -----------------------------------------------------------------------------

# Roles with assigned permissions

#

# Each line conforms to the format defined in the

# org.apache.shiro.realm.text.TextConfigurationRealm#setRoleDefinitions JavaDoc

# -----------------------------------------------------------------------------

[roles]

# 'admin' role has all permissions, indicated by the wildcard '*'

admin = *

# The 'schwartz' role can do anything (*) with any lightsaber:

schwartz = lightsaber:*

# The 'goodguy' role is allowed to 'drive' (action) the winnebago (type) with

# license plate 'eagle5' (instance specific id)

goodguy = winnebago:drive:eagle5

导入相关依赖 pom.xml,官网未给出详细的依赖,具体的参考给出的git下载的文件,然后做了一些简单的修改。

xmlns:xsi="http://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">

Shiro

com.nuist

1.0-SNAPSHOT

4.0.0

hello-shiro

8

8

org.apache.shiro

shiro-core

1.4.1

org.slf4j

jcl-over-slf4j

1.7.21

org.slf4j

slf4j-log4j12

1.7.12

log4j

log4j

1.2.17

xmlns:xsi="http://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">

Shiro

com.nuist

1.0-SNAPSHOT

4.0.0

hello-shiro

8

8

org.apache.shiro

shiro-core

1.4.1

org.slf4j

jcl-over-slf4j

1.7.21

org.slf4j

slf4j-log4j12

1.7.12

log4j

log4j

1.2.17

log4j.prop[erties:

log4j.rootLogger=INFO, stdout

log4j.appender.stdout=org.apache.log4j.ConsoleAppender

log4j.appender.stdout.layout=org.apache.log4j.PatternLayout

log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - %m%n

最重要的配置文件:

QuickStart:

import org.apache.shiro.SecurityUtils;

import org.apache.shiro.authc.*;

import org.apache.shiro.mgt.DefaultSecurityManager;

import org.apache.shiro.mgt.SecurityManager;

import org.apache.shiro.realm.text.IniRealm;

import org.apache.shiro.session.Session;

import org.apache.shiro.subject.Subject;

import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

import javax.naming.InitialContext;

public class Quickstart {

private static final transient Logger log = LoggerFactory.getLogger(Quickstart.class);

public static void main(String[] args) {

// 旧方法,由于shiro更新无法正常使用

// Factory factory = new IniSecurityManagerFactory("classpath:shiro.ini");

// SecurityManager securityManager = factory.getInstance();

// 新方法 shiro更新问题 解决正常运行

DefaultSecurityManager securityManager = new DefaultSecurityManager();

IniRealm iniRealm = new IniRealm("classpath:shiro.ini");

securityManager.setRealm(iniRealm);

SecurityUtils.setSecurityManager(securityManager);

// Now that a simple Shiro environment is set up, let's see what you can do:

// 获取当前用户对象

Subject currentUser = SecurityUtils.getSubject();

// 通过当前用户拿到session

Session session = currentUser.getSession();

session.setAttribute("someKey", "aValue");

String value = (String) session.getAttribute("someKey");

if (value.equals("aValue")) {

log.info("subject =>! [" + value + "]");

}

// 判断当前用户是否被认证

if (!currentUser.isAuthenticated()) {

UsernamePasswordToken token = new UsernamePasswordToken("lonestarr", "vespa");

token.setRememberMe(true); // 设置记住我

try {

currentUser.login(token);

} catch (UnknownAccountException uae) {

log.info("There is no user with username of " + token.getPrincipal());

} catch (IncorrectCredentialsException ice) {

log.info("Password for account " + token.getPrincipal() + " was incorrect!");

} catch (LockedAccountException lae) {

log.info("The account for username " + token.getPrincipal() + " is locked. "kdkqBkzbj +

"Please contact your administrator to unlock it.");

}

// 最重要的一个异常,认证异常

catch (AuthenticationException ae) {

//unexpected condition? error?

}

}

//say who they are:

//print their identifying principal (in this case, a username):

log.info("User [" + currentUser.getPrincipal() + "] logged in successfully.");

//test a role:

if (currentUser.hasRole("schwartz")) {

log.info("May the Schwartz be with you!");

} else {

log.info("Hello, mere mortal.");

}

// 测试一个简单的权限

// 粗粒度的一个权限限制

if (currentUser.isPermitted("lightsaber:wield")) {

log.info("You may use a lightsaber ring. Use it wisely.");

} else {

log.info("Sorry, lightsaber rings are for schwartz masters only.");

}

//a (very powerful) Instance Level permission:

if (currentUser.isPermitted("winnebago:drive:eagle5")) {

log.info("You are permitted to 'drive' the winnebago with license plate (id) 'eagle5'. " +

"Here are the keys - have fun!");

} else {

log.info("Sorry, you aren't allowed to drive the 'eagle5' winnebago!");

}

//注销功能

currentUser.logout();

System.exit(0);

}

}

以上主要的几个关键部分代码:

对象初始化部分

// 新方法 shiro更新问题 解决正常运行

DefaultSecurityManager securityManager = new DefaultSecurityManager();

IniRealm iniRealm = new IniRealm("classpath:shiro.ini");

securityManager.setRealm(iniRealm);

SecurityUtils.setSecurityManager(securityManager);

获取当前用户

Subject currentUser = SecurityUtils.getSubject();

判断用户是否被认证

!currentUser.isAuthenticated()

判断用户是否具有什么角色

currentUser.hasRole("schwartz")

判断用户是否拥有权限

currentUser.isPermitted("lightsaber:wield")

注销

currentUser.logout();

此时我们运行启动,项目如下,那么一个简单的shiro quickStart 就已经启动好了。

注意

shir最重要的三个部分:

subject 用户SecurityManager 管理所有的用户Realm 连接数据

3.SpringBoot中集成

1.导入shiro相关依赖

org.apache.shiro

shiro-spring

1.6.0

2.自定义UserRealm

package com.nuist.shirospringboot.config;

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;

/**

* @author liuhuanhuan

* @version 1.0

* @date 2022/5/8 17:59

* @Description

*/

public class UserRealm extends AuthorizingRealm {

@Override

protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {

System.out.println("执行了=》授权doGetAuthorizationInfo方法");

return null;

}

@Override

protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {

System.out.println("执行了-》认证doGetAuthenticationInfo");

return null;

}

}

3.定义shiroConfig

package com.nuist.shirospringboot.config;

import org.apache.shiro.spring.web.ShiroFilterFactoryBean;

import org.apache.shiro.web.mgt.DefaultWebSecurityManager;

import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;

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

import org.springframework.context.annotation.Bean;

import org.springframework.context.annotation.Configuration;

/**

* @author liuhuanhuan

* @version 1.0

* @date 2022/5/8 17:58

* @Description

*/

@Configuration

public class ShiroConfig {

// shiroFilterConfiguere

@Bean

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

ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();

// 设置用户管理器

shiroFilterFactoryBean.setSecurityManager(securityManager);

return shiroFilterFactoryBean;

}

// defaultWebSecurity

// 通过@Qualifier 是USerRealm进行绑定

@Bean

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

DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();

// 关联Realm

securityManager.setRealm(userReaml);

return securityManager;

}

// 创建realm对象 需要去进行自定义,这样就可以交给spring去进行托管了

@Bean

public UserRealm userReaml(){

return new UserRealm();

}

}

4.新建页面进行测试

package com.nuist.shirospringboot.controller;

import org.springframework.stereotype.Controller;

import org.springframework.ui.Model;

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

/**

* @author liuhuanhuan

* @version 1.0

* @date 2022/5/8 17:52

* @Description

*/

@Controller

public class Mycontrollrt

{

@RequestMapping({"/","/index"})

public String toIndex(Model model) {

model.addAttribute("msg","hello shiro");

return "index";

}

@RequestMapping("/user/add")

public String add() {

return "user/add";

}

@RequestMapping("/user/update")

public String update() {

return "user/update";

}

}

index.html

add | update

user/add.html

user/update.html

此时一个简单的项目就搭建起来了,然后开始shiro的认证授权的操作。

我们只需要在配置中添加如下代码:

Map filterMap = new LinkedHashMap<>();

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

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

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

shiroFilterFactoryBean.setFilterChainDefinitionMap(filterMap);

shiroFilterFactoryBean.setLoginUrl("/toLogin");

此时就对我们所有的页面请求进行了拦截,然后转发到login的页面

login.html:

用户名:

密码:

此时在页面进行点击的时候,我们就无法正常进入页面,只能进入到我们的登录页面

进行登录验证的拦截,只有输入正确的账号密码才能够进入:

MyCOntroller中新增如下代码:

@RequestMapping("/login")

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

// 获取当前用户

Subject subject = SecurityUtils.getSubject();

// 封装当前用户

UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken(username, password);

try {

subject.login(usernamePasswordToken); // 执行登录的方法,有异常进行处理

return "index";

} catch (UnknownAccountException e){

model.addAttribute("msg","用户名错误");

return "login";

} catch (IncorrectCredentialsException e) { // 密码不存在

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

return "login";

}

}

然后修改login页面的代码

用户名:

密码:

然后在我们的UserRealm

中doGetAuthenticationInfo方法中新增代码

@Override

protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {

System.out.println("执行了-》认证doGetAuthenticationInfo");

String name = "root";

String password = "123456";

UsernamePasswordToken authenticationToken1 = (UsernamePasswordToken) authenticationToken;

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

return null; // 抛出异常

}

// 密码认证 shiro去做

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

}

此时我们通过UsernamePasswordToken 获取我们封装好的账号和密码,但是我们只需要进行账号的认证,密码的认证交给我们的shiro去做就可以了。

具体的用户授权,我们可以进行连接数据库的设置,但是我为了偷懒,我就不去手动创建与数据库的链接啦。

下面我们来进行页面的授权操作

我们想要进行用户的授权操作

我们需要在shiroConfig中新增如下代码:

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

此时代表如果用户拥有user:add操作的话,可以显示,如果没有的话就不能正常显示

我们可以自定义一个页面来用于返回信息的显示:

@RequestMapping("/noauth")

@ResponseBody

public String noauth() {

return "未经过授权无法进行访问";

}

当用户没有add权限的时候,我们就提示无法显示:

此时我们就完成了单个的用户授权的操作。此时我们再去进行具体的页面操作

shiro与thymeleaf的结合:

需要将我们进行验证的页面进行如下操作:

xmlns:shiro="http://thymeleaf.org/thymeleaf-extras-shiro">

登录

add

|

update

此时应用的方式和springsecurity的方式基本一致。

然后在我们的授权页面进行操作如下:

UserRealm中修改doGetAuthorizationInfo方法,如下:

@Override

protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {

System.out.println("执行了=》授权doGetAuthorizationInfo方法");

SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();

// 新增授权页面

authorizationInfo.addStringPermission("user:add");

// 拿到当前对象 ,然后通过对象中的授权方式进行判断

return authorizationInfo;

}

此时我们赋予用户只有add的权限,那么按理说在页面中是无法显示update的按钮,那么我们进行测试下,是否可以正常使用:

此时认证授权部分已经成功啦,以上就是我们进行的一个小小的demo,更深入的学习,后续继续更新。

git源码地址


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:Java实现驼峰和下划线互相转换的示例代码(js下划线转驼峰处理)
下一篇:Java线程池的优点及池化技术的应用(java线程池的技术框架是如何定义实现的)
相关文章

 发表评论

暂时没有评论,来抢沙发吧~