博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Springboot集成Shiro实现认证
阅读量:4045 次
发布时间:2019-05-24

本文共 6530 字,大约阅读时间需要 21 分钟。

Springboot集成Shiro实现认证

Apache Shiro是什么?

Apache Shiro是一个强大且易用的Java安全框架,能够执行身份验证、授权、加密和会话管理等。

Apache Shiro的主要API

Subject

Subject为“当前操作用户”。但是,在Shiro中,Subject这一概念可以理解为"账户",但并不局限于"帐户",而是与shrio交互的当前应用。

SecurityManager

SecurityManager(安全管理器)是Shiro框架的核心,Shiro通过SecurityManager实现安全管理的功能和服务。

Realm

  • Realm是安全数据源,其中包含认证和授权数据。

    认证可以理解为登录,认证数据为正确的账户及口令信息,当对用户执行认证(登录)时,shiro会与Realm中的认证数据比较进行登录验证。

    授权数据可以理解为用户拥有的权限,当用户进行某一操作时,Shiro会与Realm中的授权数据比对,验证用户是否拥有此操作的权限(授权验证)。

  • 当配置Shiro时,你必须至少指定一个Realm,用于认证和(或)授权。

    Shiro内置了很多可用的安全数据源(又名目录)的Realm, 如果内置的Realm不能满足需求,可以自定义Realm实现。

Apache Shiro与Springboot集成

依赖引入

org.apache.shiro
shiro-spring-boot-web-starter
1.4.1

开发集成shiro的配置类

开发一个集成shiro的spring配置类

@Configurationpublic class ShiroConfigure {
private static final Logger LOG = LoggerFactory.getLogger(ShiroConfigure.class); //注册跨域过滤器 //开发和配置安全数据源 //配置shiro过滤器拦截规则定义 }

注册跨域过滤器

shiro过滤器会优先于springboot拦截请求,springboot的跨域设置将不起作用,因此需要专门注册跨域过滤器并设置其为过滤器链中的第一个。

@Bean    public FilterRegistrationBean
corsFilter() {
final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); final CorsConfiguration config = new CorsConfiguration(); // 允许cookies跨域 config.setAllowCredentials(true); // 允许向该服务器提交请求的URI,*表示全部允许,在SpringMVC中,如果设成*,会自动转成当前请求头中的Origin config.addAllowedOrigin("*"); // 允许访问的头信息,*表示全部 config.addAllowedHeader("*"); // 预检请求(options请求)的缓存时间(秒),即在这个时间段里,对于相同的跨域请求不会再预检了 config.setMaxAge(1L); // 允许提交请求的方法,*表示全部允许 config.addAllowedMethod("*"); /* config.addAllowedMethod("OPTIONS"); config.addAllowedMethod("HEAD"); config.addAllowedMethod("GET"); config.addAllowedMethod("PUT"); config.addAllowedMethod("POST"); config.addAllowedMethod("DELETE"); config.addAllowedMethod("PATCH"); */ //设置允许跨域的路径 source.registerCorsConfiguration("/**", config); FilterRegistrationBean
bean = new FilterRegistrationBean
(new CorsFilter(source)); // 设过滤器的优先级 bean.setOrder(0); return bean; }

开发和配置安全数据源

/*	 * 配置安全数据源Realm 此处必须要命名“authorizer”,	 * 因为shiro会自动寻找名称为“authorizer”的、并实现接口Authorizer的对象,	 * 而AuthorizingRealm正是接口Authorizer的实现类	 */	@Bean("authorizer")	@Autowired	public AuthorizingRealm saftyRealm(ShiroService shiroService) {
return new AuthorizingRealm() {
/** * 获取认证信息(即包含当前用户帐户和合法密码等信息) shiro在登录认证时需要通过该方法获取认证信息。 参数 AuthenticationToken * 认证令牌(如:一组用户名和密码就是一个认证令牌) */ @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) {
String userId = (String) token.getPrincipal();// 获得当事人(当前用户账号) User user = shiroService.getUser(userId); /* * 如果不存在前用户信息,返回null */ if (user == null) {
return null; } /* * 创建当前用户 */ CurrUser currUser = new CurrUser(user.getU_id(), user.getU_name()); /* * 创建认证信息,三个构造参数含义依次如下: 参数1:principal当前用户 参数2:credentials认证凭证(如:口令、密码等) * 参数3:realm名称 */ SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(currUser, user.getU_pwd(), this.getName()); /* * 返回认证信息 */ return info; } /** * 获取当事人(当前用户)授权信息,shiro在检查访问是否经过授权时需要通过该方法获取授权信息。(本例不考虑授权验证,因此返回null) * 参数PrincipalCollection 当事人集合 */ @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
// TODO Auto-generated method stub return null; } }; }

配置shiro过滤器拦截规则定义

@Bean	@Autowired	public ShiroFilterChainDefinition shiroFilterChainDefinition(ShiroService shiroService) {
DefaultShiroFilterChainDefinition chainDefinition = new DefaultShiroFilterChainDefinition(); /* * 可匿名访问资源 */ chainDefinition.addPathDefinition("/safty/login/**", "anon"); // 其它资源必须经过认证 chainDefinition.addPathDefinition("/**", "authc"); LOG.debug("=====Shiro安全规则======================================================================="); LOG.debug(chainDefinition.getFilterChainMap().toString()); LOG.debug("=====Shiro安全规则======================================================================="); return chainDefinition; }

在配置文件application.yaml中配置shiro

shiro:  loginUrl: /safty/login/loginTo #拦截需要认证而未认证的请求后的跳转路径

登录示例

@RestController@RequestMapping("/safty/login")public class LoginController {
@PostMapping("/user") public Result login(@RequestBody UserDto userDto) {
try {
Subject subject = SecurityUtils.getSubject(); // 创建登录令牌 UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken(userDto.getU_id(), userDto.getU_pwd()); // 登录,该方法声明抛出异常,可以捕获异常,并进行应对处理 subject.login(usernamePasswordToken); // 是否通过认证 if (subject.isAuthenticated()) {
// 获得当前用户信息 CurrUser currUser = (CurrUser) subject.getPrincipal(); // 将当前用户放入Session。注:这里的Session是由Shiro提供的。 subject.getSession().setAttribute(Constants.SESSION_ATTR_CURR_USER, currUser); return Result.success("登录成功!"); } return Result.fail("登录失败!"); } catch (UnknownAccountException e) {
return Result.fail("用户名不存在!"); } catch (IncorrectCredentialsException e) {
return Result.fail("账户密码不正确!"); } catch (LockedAccountException e) {
return Result.fail("用户名被锁定 !"); } catch (Exception e) {
e.printStackTrace(); return Result.fail("系统错误!"); } } @GetMapping("/loginTo") public Result loginTo() {
return Result.unLogged(); }}

退出示例

@RestController@RequestMapping("/safty/home")public class HomeController {
//...... //退出系统 @DeleteMapping("/user") public Result logout() {
SecurityUtils.getSubject().getSession().removeAttribute(Constants.SESSION_ATTR_CURR_USER); //注销 SecurityUtils.getSubject().logout(); return Result.success("您已成功退出系统!"); }}

其它相关类和配置文件

ShiroService

public interface ShiroService {
/** * 获取用户信息 * @param userId * @return */ User getUser(String userId); }

ShiroDao

public interface ShiroDao {
/** * 根据用户帐号查询用户信息 * @param userId * @return */ @Select("select u_id,u_name,u_pwd from sys_user where u_id=#{userId}") User findUser(String userId); }

启动类

@SpringBootApplication@MapperScan({
"org.sunshine.dye.dao", "org.sunshine.dye.shiro.dao" })public class SunshineDyeApp {
public static void main(String[] args) {
SpringApplication.run(SunshineDyeApp.class, args); }}

修改日志配置

logging:  level:    web: trace    org.sunshine.dye.dao: debug    org.sunshine.dye.shiro.dao: debug

测试

上述配置和相关代码开发完成后,即可进行测试调试。

附:案例源码

转载地址:http://anhdi.baihongyu.com/

你可能感兴趣的文章
VMware Workstation Pro虚拟机不可用解决方法
查看>>
最简单的使用redis自带程序实现c程序远程访问redis服务
查看>>
redis学习总结-- 内部数据 字符串 链表 字典 跳跃表
查看>>
iOS 对象序列化与反序列化
查看>>
iOS 序列化与反序列化(runtime) 01
查看>>
iOS AFN 3.0版本前后区别 01
查看>>
iOS ASI和AFN有什么区别
查看>>
iOS QQ侧滑菜单(高仿)
查看>>
iOS 扫一扫功能开发
查看>>
iOS app之间的跳转以及传参数
查看>>
iOS __block和__weak的区别
查看>>
Android(三)数据存储之XML解析技术
查看>>
Spring JTA应用之JOTM配置
查看>>
spring JdbcTemplate 的若干问题
查看>>
Servlet和JSP的线程安全问题
查看>>
GBK编码下jQuery Ajax中文乱码终极暴力解决方案
查看>>
Oracle 物化视图
查看>>
PHP那点小事--三元运算符
查看>>
解决国内NPM安装依赖速度慢问题
查看>>
Brackets安装及常用插件安装
查看>>