SpringBoot微服务开发——Shiro(安全)

文章目录

  • SpringBoot微服务开发——Shiro(安全)
    • Shiro(安全)
      • 1、Shiro简介
      • 2、Shiro有哪些功能?
      • 3、Shiro架构(外部)
      • 4、Shiro架构(内部)
      • 5、进入实践
        • 1、导入依赖
        • 2、配置文件
        • 3、测试Quickstart
      • 6、SpringBoot整合Shiro环境搭建
      • 7、shiro实现登录拦截
      • 8、Shiro实现用户认证
      • 9、Shiro整合Mybatis
      • 10、Shiro请求授权实现
        • 1、授权正常的情况下,没有授权会跳转到未授权页面
        • 2、授予可以访问的权限
        • 3、一般在数据库里添加权限的字段,修改数据库,和实体类

Shiro(安全)

1、Shiro简介

​ Apache Shiro是一个强大且易用的Java安全框架,执行身份验证、授权、密码和会话管理。使用Shiro的易于理解的API,您可以快速、轻松地获得任何应用程序,从最小的移动应用程序到最大的网络和企业应用程序。

Shiro可以非常容易的开发出足够好的应用,不仅可以用在JavaSE环境,也可以用在JavaEE环境。

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

2、Shiro有哪些功能?

  1. Authentication: 身份认证、登录,验证用户是不是拥有相应的身份;
  2. Authorization:授权,即权限验证,验证某个已认证的用户是否拥有某个权限,即判断用户能否进行什么操
  3. 作,如:验证某个用户是否拥有某个角色,或者细粒度的验证某个用户对某个资源是否具有某个权限!
  4. Session Manager:会话管理,即用户登录后就是第一次会话,在没有退出之前,它的所有信息都在会话中;
  5. 会话可以是普通的avaSE环境,也可以是Web环境;
  6. Cnyptography: 加密,保护数据的安全性,如密码加密存储到数据库中,而不是明文存储;
  7. Web Support: Web支持,可以非常容易的集成到Web环境;
  8. Caching: 缓存,比如用户登录后,其用户信息,拥有的角色、权限不必每次去查,这样可以提高效率
  9. Concurrency: Shiro支持多线程应用的并发验证,即,如在一个线程中开启另一 个线程,能把权限自动的传
    播过去
  10. Testing:提供测试支持;
  11. Run As: 允许一 个用户假装为另- -个用户(如果他们允许)的身份进行访问;
  12. Remember Me:记住我,这个是非常常见的功能,即一次登录后,下次再来的话不用登录了

3、Shiro架构(外部)

  1. subject: 应用代码直接交互的对象是Subject, 也就是说Shiro的对外API核心就是Subject, Subject代表了当
    前的用户,这个用户不-定是一个具体的人, 与当前应用交互的任何东西都是Subject,如网络爬虫,机器人
    等,与Subject的所有交互都会委托给SecurityManager; Subject其实是一 个门面, SecurityManageer 才是
    实际的执行者
  2. SecurityManager: 安全管理器,即所有与安全有关的操作都会与SercurityManager交互,并且它管理着所有
    的Subject,可以看出它是Shiro的核心,它负责与Shiro的其他组件进行交互,它相当于SpringMVC的
    DispatcherServlet的角色
  3. Realm: Shiro从Realm获取安全数据 (如用户,色,权限),就是说SecurityManager 要验证用户身份,
    那么它需要从Realm获取相应的用户进行比较,来确定用户的身份是否合法;也需要从Realm得到用户相应的
    角色、权限,进行验证用户的操作是否能够进行,可以把Realm看成DataSource;

4、Shiro架构(内部)

  1. Subject: 任何可以与应用交互的"用户;3
  2. Security Manager:相当于SpringMVC中的DispatcherServlet;是Shiro的心脏,所有具体的交互都通过
  3. Security Manager进行控制,它管理者所有的Subject,且负责进行认证,授权,会话,及缓存的管理。
  4. Authenticator: 负责Subject认证,是一一个扩 展点,可以自定义实现;可以使用认证策略(AuthenticationStrategy),即什么情况下算用户认证通过了;
  5. Authorizer:授权器,即访问控制器,用来决定主体是否有权限进行相应的操作;即控制着用户能访问应用中
    的那些功能;
  6. Realm: 可以有一个或者多个的realm,可以认为是安全实体数据源,即用于获取安全实体的,可以用DBC实
    现,也可以是内存实现等等,由用户提供;所以- -般在应用中都需要实现自己的realm
  7. SessionManager: 管理Session生命周期的组件,而Shiro并不仅仅可以用在Web环境,也可以用在普通的
    JavaSE环境中
  8. CacheManager: 缓存控制器,来管理如用户,角色,权限等缓存的;因为这些数据基本上很少改变,放到缓
    存中后可以提高访问的性能;
  9. Cryptography:密码模块, Shiro 提高了一些常见的加密组件用于密码加密, 解密等

5、进入实践

打开官网文档: http://shiro.apache.org//tutorial.html

  1. 创建一个普通的maven父工程
  2. 创建一个普通的Maven子工程: shiro-01-helloworld
  3. 根据官方文档,我们来导入Shiro的依赖

1、导入依赖

<dependencies><!-- https://mvnrepository.com/artifact/org.apache.shiro/shiro-core --><dependency><groupId>org.apache.shiro</groupId><artifactId>shiro-core</artifactId><version>1.8.0</version></dependency><!-- configure logging --><dependency><groupId>org.slf4j</groupId><artifactId>jcl-over-slf4j</artifactId><version>1.7.21</version></dependency><dependency><groupId>org.slf4j</groupId><artifactId>slf4j-log4j12</artifactId><version>1.7.21</version></dependency><!-- https://mvnrepository.com/artifact/org.apache.logging.log4j/log4j-core --><dependency><groupId>org.apache.logging.log4j</groupId><artifactId>log4j-core</artifactId><version>2.14.1</version></dependency></dependencies>

2、配置文件

resources目录下

log4j.properties

log4j.rootLogger=INFO, stdoutlog4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - %m %n# General Apache libraries
log4j.logger.org.apache=WARN# Spring
log4j.logger.org.springframework=WARN# Default Shiro logging
log4j.logger.org.apache.shiro=INFO# Disable verbose logging
log4j.logger.org.apache.shiro.util.ThreadContext=WARN
log4j.logger.org.apache.shiro.cache.ehcache.EhCache=WARN

shiro.ini,需要安装ini插件

[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

3、测试Quickstart

/** Licensed to the Apache Software Foundation (ASF) under one* or more contributor license agreements.  See the NOTICE file* distributed with this work for additional information* regarding copyright ownership.  The ASF licenses this file* to you under the Apache License, Version 2.0 (the* "License"); you may not use this file except in compliance* with the License.  You may obtain a copy of the License at**     http://www.apache.org/licenses/LICENSE-2.0** Unless required by applicable law or agreed to in writing,* software distributed under the License is distributed on an* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY* KIND, either express or implied.  See the License for the* specific language governing permissions and limitations* under the License.*/import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.config.IniSecurityManagerFactory;import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.Subject;import org.apache.shiro.util.Factory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;/*** Simple Quickstart application showing how to use Shiro's API.** @since 0.9 RC2*/
public class Quickstart {//日志private static final transient Logger log = LoggerFactory.getLogger(Quickstart.class);public static void main(String[] args) {// The easiest way to create a Shiro SecurityManager with configured// realms, users, roles and permissions is to use the simple INI config.// We'll do that by using a factory that can ingest a .ini file and// return a SecurityManager instance:// Use the shiro.ini file at the root of the classpath// (file: and url: prefixes load from files and urls respectively):Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro.ini");SecurityManager securityManager = factory.getInstance();// for this simple example quickstart, make the SecurityManager// accessible as a JVM singleton.  Most applications wouldn't do this// and instead rely on their container configuration or web.xml for// webapps.  That is outside the scope of this simple quickstart, so// we'll just do the bare minimum so you can continue to get a feel// for things.SecurityUtils.setSecurityManager(securityManager);// Now that a simple Shiro environment is set up, let's see what you can do:// get the currently executing user://获取当前的用户对象  SubjectSubject currentUser = SecurityUtils.getSubject();// Do some stuff with a Session (no need for a web or EJB container!!!)//通过当前对象获取当前用户的SessionSession session = currentUser.getSession();session.setAttribute("someKey", "aValue");//将aValue的session保存在someKey中String value = (String) session.getAttribute("someKey");if (value.equals("aValue")) {log.info("Subject==》session [" + value + "]");}// let's login the current user so we can check against roles and permissions://判断当前的用户是否被认证if (!currentUser.isAuthenticated()) {//Token 令牌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.  " +"Please contact your administrator to unlock it.");}// ... catch more exceptions here (maybe custom ones specific to your application?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.");}//test a typed permission (not instance-level)//简单 粗粒度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!");}//all done - log out!//注销currentUser.logout();//结束System.exit(0);}
}

这些功能在Spring-Secutiry都有

//获取当前的用户对象  Subject
Subject currentUser = SecurityUtils.getSubject();//通过当前对象获取当前用户的SessionSession session = currentUser.getSession();//判断当前的用户是否被认证currentUser.isAuthenticated()//获取当前用户信息currentUser.getPrincipal()//测试角色  判断当前用户是什么角色currentUser.hasRole("schwartz")currentUser.isPermitted("lightsaber:wield")//注销
currentUser.logout();

6、SpringBoot整合Shiro环境搭建

导入相关依赖

<!-- https://mvnrepository.com/artifact/org.apache.shiro/shiro-core --><dependency><groupId>org.apache.shiro</groupId><artifactId>shiro-core</artifactId><version>1.8.0</version></dependency><!--shiro整合spring的包--><dependency><groupId>org.apache.shiro</groupId><artifactId>shiro-spring</artifactId><version>1.8.0</version></dependency><!--thymeleaf模板,我们都是基于3.x开发--><dependency><groupId>org.thymeleaf</groupId><artifactId>thymeleaf-spring5</artifactId></dependency><dependency><groupId>org.thymeleaf.extras</groupId><artifactId>thymeleaf-extras-java8time</artifactId></dependency>

测试SpringBoot环境是否搭建成功

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body>
<h1>首页</h1>
<p th:text="${msg}"></p>
<hr><a th:href="@{/user/add}">add</a><a th:href="@{/user/update}">update</a>
</body>
</html>

controller层

@RequestMapping({"/","/index"})
public String ToIndex(Model model){model.addAttribute("msg","hello Shiro");return "index";
}

测试SpringBoot整合Shiro环境搭建成功

Shiro配置

package com.kk.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;//自定义的 UserRealm         extends AuthorizingRealm
public class UserRealm extends AuthorizingRealm {//授权@Overrideprotected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {System.out.println("执行科=》授权doGetAuthorizationInfo");return null;}//认证@Overrideprotected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {System.out.println("执行科=》认证doGetAuthenticationInfo");return null;}
}

ShiroConfig

package com.kk.config;import org.apache.shiro.mgt.DefaultSecurityManager;
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;import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;@Configuration
public class ShiroConfig {//ShiroFilterFactortBean  第三步@Beanpublic ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("securityManager") DefaultWebSecurityManager defaultWebSecurityManager) {ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();//设置安全管理器bean.setSecurityManager(defaultWebSecurityManager);return bean;}//DefaultWebSecurityManager  第二步@Bean(name = "securityManager")public DefaultWebSecurityManager getDefaultwebSecurityManager(@Qualifier("userRealm") UserRealm userRealm) {DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();//.关联UserReaLmsecurityManager.setRealm(userRealm);return securityManager;}//创建 realm 对象  需要自定义  第一步@Beanpublic UserRealm userRealm() {return new UserRealm();}}

MyController

package com.kk.controller;import org.springframework.jmx.export.annotation.ManagedResource;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;@Controller
public class MyController {@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";}@RequestMapping("/toLogin")public String toLogin(){return "login";}}

index.html

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body>
<h1>首页</h1>
<p th:text="${msg}"></p>
<hr><a th:href="@{/user/add}">add</a><a th:href="@{/user/update}">update</a>
</body>
</html>

add.html

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body>
<h1>add</h1>
</body>
</html>

update.html

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body>
<h1>update</h1>
</body>
</html>

7、shiro实现登录拦截

package com.kk.config;import org.apache.shiro.mgt.DefaultSecurityManager;
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;import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;@Configuration
public class ShiroConfig {//ShiroFilterFactortBean  第三步@Beanpublic ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("securityManager") DefaultWebSecurityManager defaultWebSecurityManager) {ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();//设置安全管理器bean.setSecurityManager(defaultWebSecurityManager);//添加shiro的内置过滤器/*anon : 无需认证就可以访问authc:必须认证才能访问user:必须拥有 记住我 功能才能用perms 拥有某个资源的权限才能访问role 拥有某个角色的权限才能访问*/Map<String, String> filterMap = new LinkedHashMap<>();filterMap.put("/user/add", "authc");filterMap.put("/user/update", "authc");bean.setFilterChainDefinitionMap(filterMap);//如果没有权限 ,则跳转到登陆页面bean.setLoginUrl("/toLogin");return bean;}//DefaultWebSecurityManager  第二步@Bean(name = "securityManager")public DefaultWebSecurityManager getDefaultwebSecurityManager(@Qualifier("userRealm") UserRealm userRealm) {DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();//.关联UserReaLmsecurityManager.setRealm(userRealm);return securityManager;}//创建 realm 对象  需要自定义  第一步@Beanpublic UserRealm userRealm() {return new UserRealm();}}

login.html

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body>
<h1>登陆</h1>
<hr>
<form action=""><p>用户名:<input type="text" name="username"></p><p>密码:<input type="text" name="password"></p><p><input type="submit"></p></form>
</body>
</html>

MyController

@RequestMapping("/toLogin")
public String toLogin(){return "login";
}

8、Shiro实现用户认证

MyController

@RequestMapping("/login")
public String login(String username,String password,Model model){//获取当前的用户Subject subject = SecurityUtils.getSubject();//封装登陆用户的登陆数据UsernamePasswordToken token = new UsernamePasswordToken(username, password);try{subject.login(token);//执行登陆方法,如果没有异常就说明okreturn "index";}catch (UnknownAccountException e){//用户名不存在model.addAttribute("msg","用户名错误");return "login";}catch (IncorrectCredentialsException e){//密码不存在model.addAttribute("msg","密码错误");return "login";}}

login.html

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body>
<h1>登陆</h1>
<hr>
<p th:text="${msg}" style="color: red;"></p>
<form th:action="@{/login}"><p>用户名:<input type="text" name="username"></p><p>密码:<input type="text" name="password"></p><p><input type="submit"></p></form>
</body>
</html>

UserRealm

//认证
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {System.out.println("执行了=》认证doGetAuthenticationInfo");//用户名 密码 ---数据库String name="root";String password="123456";UsernamePasswordToken userToken = (UsernamePasswordToken) token;if (!userToken.getUsername().equals(name)){return null;//抛出异常UnknownAccountException}//密码认证  shiroreturn new SimpleAuthenticationInfo("",password,"");}

9、Shiro整合Mybatis

导入依赖

<!--        连接数据库--><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId></dependency><dependency><groupId>log4j</groupId><artifactId>log4j</artifactId><version>1.2.17</version></dependency><dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId><version>1.2.6</version></dependency>
<!--        引入mybatis-springboot--><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>2.2.0</version></dependency>

2.连接数据库application.yml

spring:datasource:username: rootpassword: 981204#?serverTimezone=UTC解决时区的报错url: jdbc:mysql://localhost:3306/mybatis?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8driver-class-name: com.mysql.jdbc.Drivertype: com.alibaba.druid.pool.DruidDataSource#Spring Boot 默认是不注入这些属性值的,需要自己绑定#druid 数据源专有配置initialSize: 5minIdle: 5maxActive: 20maxWait: 60000timeBetweenEvictionRunsMillis: 60000minEvictableIdleTimeMillis: 300000validationQuery: SELECT 1 FROM DUALtestWhileIdle: truetestOnBorrow: falsetestOnReturn: falsepoolPreparedStatements: true#配置监控统计拦截的filters,stat:监控统计、log4j:日志记录、wall:防御sql注入#如果允许时报错  java.lang.ClassNotFoundException: org.apache.log4j.Priority#则导入 log4j 依赖即可,Maven 地址: https://mvnrepository.com/artifact/log4j/log4jfilters: stat,wall,log4jmaxPoolPreparedStatementPerConnectionSize: 20useGlobalDataSourceStat: trueconnectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=500

3.设置application.properties

# 整合mybatis
mybatis.type-aliases-package=com.kk.pojo
mybatis.mapper-locations=classpath:mapper/*.xml

4.实体类

package com.kk.pojo;public class User {private int id;private String name;private String pwd;public User() {}public User(int id, String name, String pwd) {this.id = id;this.name = name;this.pwd = pwd;}public int getId() {return id;}public void setId(int id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getPwd() {return pwd;}public void setPwd(String pwd) {this.pwd = pwd;}@Overridepublic String toString() {return "User{" +"id=" + id +", name='" + name + '\'' +", pwd='" + pwd + '\'' +'}';}
}

5.UserMapper

package com.kk.mapper;import org.apache.ibatis.annotations.Mapper;
import org.springframework.stereotype.Repository;@Repository
@Mapper
public class UserMapper {public User queryUserByName(String name);
}

6.UserMapper.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.kk.mapper.UserMapper"><select id="queryUserByName" resultType="User">select * from mybatis.user where name = #{name}</select></mapper>

7.UserService

public interface UserService {public User queryUserByName(String name);
}

8.UserServiceImpl

package com.kk.service;import org.springframework.stereotype.Service;@Service
public class UserServiceImp implements UserService{@AutowiredUserMapper userMapper;@Overridepublic User queryUserByName(String name) {return userMapper.queryUserByName(name);}
}

9.测试查出对应User

@SpringBootTest
class ShiroSpringbootApplicationTests {@AutowiredUserServiceImpl userService;@Testvoid contextLoads() {System.out.println(userService.queryUserByName("雏田"));}
}

10、测试成功后 将数据绑定到安全配置中,再次启动配置

package com.kk.config;import com.kk.pojo.User;
import com.kk.service.UserService;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;//自定义的 UserRealm         extends AuthorizingRealm
public class UserRealm extends AuthorizingRealm {@AutowiredUserService userService;//授权@Overrideprotected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {System.out.println("执行了=》授权doGetAuthorizationInfo");return null;}//认证@Overrideprotected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {System.out.println("执行了=》认证doGetAuthenticationInfo");UsernamePasswordToken userToken = (UsernamePasswordToken) token;//连接真实数据库User user = userService.queryUserByName(userToken.getUsername());if (user==null){ //没有这个用户return null; //抛出异常UnknownAccountException}//密码认证  shiro//可以加密 MD5加密 MD5盐值加密return new SimpleAuthenticationInfo("",user.getPwd(),"");}
}

10、Shiro请求授权实现

1、授权正常的情况下,没有授权会跳转到未授权页面

package com.kk.config;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;import java.util.LinkedHashMap;
import java.util.Map;@Configuration
public class ShiroConfig {//ShiroFilterFactoryBean:3@Beanpublic ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("securityManager") DefaultWebSecurityManager defaultWebSecurityManager) {ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();//设置安全管理器bean.setSecurityManager(defaultWebSecurityManager);/*anon:无需认 证就可以访问authc:必须认证了 才能让问user:.必须拥有 记住我功能才能用perms:拥有对某个资源的权限才能访间:role:拥有某 个角色权限才能访问*/Map<String, String> filterMap = new LinkedHashMap<>();//授权,正常的情况下,没有授权会跳转到未授权页面filterMap.put("/user/add", "perms[user:add]");filterMap.put("/user/update", "perms[user:update]");//第二个为权限,只有persm=user:add/user:update] 才可能进入相应的页面filterMap.put("/user/*", "authc");//filterMap.put("/user/add", "authc");//filterMap.put("/user/update", "authc");bean.setFilterChainDefinitionMap(filterMap);//设置获录的请求bean.setLoginUrl("/toLogin");//未授权页面bean. setUnauthorizedUrl("/noauth");return bean;}//Dafaul tWebSecurityManager:2@Bean(name = "securityManager")public DefaultWebSecurityManager getDefaultwebSecurityManager(@Qualifier("userRealm") UserRealm userRealm) {DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();//关联UserReaLmsecurityManager.setRealm(userRealm);return securityManager;}//创建UserRealm对象,需要自定义类:1@Beanpublic UserRealm userRealm() {return new UserRealm();}
}

controller

@RequestMapping("/noauth")
@ResponseBody
public String unauthorized() {return "未经授权无法访问此页面";
}

2、授予可以访问的权限

package com.kk.config;import com.kk.pojo.User;
import com.kk.service.UserService;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;public class UserRealm extends AuthorizingRealm {@AutowiredUserService userService;@Overrideprotected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {System.out.println("执行了=》授权doGetAuthorizationInfo");//SimpleAuthorizationInfoSimpleAuthorizationInfo info = new SimpleAuthorizationInfo();info.addStringPermission("user:add");return info;}@Overrideprotected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {System.out.println("执行了=》验证doGetAuthorizationInfo");UsernamePasswordToken userToken = (UsernamePasswordToken) token;//连接真实的数据库User user = userService.queryUserByName(userToken.getUsername());if (user == null) { //没有这个用户return null; //UnknownAccountException}//可以加密: MD5: e10adc3949ba59abbe56e057f20f883e MD5 盐值加密: e10adc3949ba59abbe56e057f20f883eusername//密码认证, shiro 做~return new SimpleAuthenticationInfo("", user.getPwd(), "");}
}

3、一般在数据库里添加权限的字段,修改数据库,和实体类

实体类

private int id;private String name;private String pwd;private String perms;

UserRealm实现授权的分配

package com.kk.config;import com.kk.pojo.User;
import com.kk.service.UserService;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;public class UserRealm extends AuthorizingRealm {@AutowiredUserService userService;@Overrideprotected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {System.out.println("执行了=》授权doGetAuthorizationInfo");//SimpleAuthorizationInfoSimpleAuthorizationInfo info = new SimpleAuthorizationInfo();//info.addStringPermission("user:add");//拿到当登录 的这个对象Subject subject = SecurityUtils.getSubject();User currentUser = (User) subject.getPrincipal(); //拿到User对象//设置当前用户的权限info.addStringPermission(currentUser.getPerms());return info;}@Overrideprotected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {System.out.println("执行了=》验证doGetAuthorizationInfo");UsernamePasswordToken userToken = (UsernamePasswordToken) token;//连接真实的数据库User user = userService.queryUserByName(userToken.getUsername());if (user == null) { //没有这个用户return null; //UnknownAccountException}//可以加密: MD5: e10adc3949ba59abbe56e057f20f883e MD5 盐值加密: e10adc3949ba59abbe56e057f20f883eusername//密码认证, shiro 做~return new SimpleAuthenticationInfo(user, user.getPwd(), "");}
}

3.使用shirothymeleaf

在html页面中导入

xmlns:shiro="http://www.thymeleaf.org/thymeleaf-extras-shiro
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org"xmlns:shiro="http://www.thymeleaf.org/thymeleaf-extras-shiro">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body>
<h1>首页</h1>
<p><a th:href="@{/toLogin}">登录</a>
</p>
<p th:text="${msg}"></p>
<hr>
<div shiro:hasPermission="user:add"><a th:href="@{/user/add}">add</a>
</div>
<div shiro:hasPermission="user:update"><a th:href="@{/user/update}">update</a>
</div></body>
</html>

4.测试

存在登录按钮的问题

UserRealm中添加session

@Overrideprotected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {System.out.println("执行了=》验证doGetAuthorizationInfo");UsernamePasswordToken userToken = (UsernamePasswordToken) token;//连接真实的数据库User user = userService.queryUserByName(userToken.getUsername());if (user == null) { //没有这个用户return null; //UnknownAccountException}Subject currentSubject = SecurityUtils.getSubject();Session session = currentSubject.getSession();session.setAttribute("loginUser",user);//可以加密: MD5: e10adc3949ba59abbe56e057f20f883e MD5 盐值加密: e10adc3949ba59abbe56e057f20f883eusername//密码认证, shiro 做~return new SimpleAuthenticationInfo(user, user.getPwd(), "");}
}

index.html

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org"xmlns:shiro="http://www.thymeleaf.org/thymeleaf-extras-shiro">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body>
<h1>首页</h1>
<div th:if="${session.loginUser==null}"><a th:href="@{/toLogin}">登录</a>
</div><p th:text="${msg}"></p>
<hr>
<div shiro:hasPermission="user:add"><a th:href="@{/user/add}">add</a>
</div>
<div shiro:hasPermission="user:update"><a th:href="@{/user/update}">update</a>
</div></body>
</html>

项目结构

nInfo");
UsernamePasswordToken userToken = (UsernamePasswordToken) token;
//连接真实的数据库
User user = userService.queryUserByName(userToken.getUsername());
if (user == null) { //没有这个用户
return null; //UnknownAccountException
}

    Subject currentSubject = SecurityUtils.getSubject();Session session = currentSubject.getSession();session.setAttribute("loginUser",user);//可以加密: MD5: e10adc3949ba59abbe56e057f20f883e MD5 盐值加密: e10adc3949ba59abbe56e057f20f883eusername//密码认证, shiro 做~return new SimpleAuthenticationInfo(user, user.getPwd(), "");}

}


index.html```html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org"xmlns:shiro="http://www.thymeleaf.org/thymeleaf-extras-shiro">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body>
<h1>首页</h1>
<div th:if="${session.loginUser==null}"><a th:href="@{/toLogin}">登录</a>
</div><p th:text="${msg}"></p>
<hr>
<div shiro:hasPermission="user:add"><a th:href="@{/user/add}">add</a>
</div>
<div shiro:hasPermission="user:update"><a th:href="@{/user/update}">update</a>
</div></body>
</html>

项目结构

[外链图片转存中…(img-z1gsNvzb-1634195014031)]

3万字《SpringBoot微服务开发——Shiro(安全)》相关推荐

  1. Springboot微服务开发教程系列:开发入门

    使用IntelliJ IDEA开发springboot入门 第一步:创建项目 第二步:填写项目信息 第三步:选择特性 第四步:等待项目创建 下载项目依赖项需要一些时间,请耐心等待 第五步:编写demo ...

  2. 基于springboot+dubbo微服务开发的商城系统

    基于springboot+dubbo微服务开发的商城系统 模仿天猫商城 更多资源,访问搬砖联盟-每天搬一点,收货多一点.

  3. springboot 搭建分布式_爱了!阿里巴巴内部出品“SpringBoot+微服务指南”,理论与实战...

    爱了爱了,Alibaba出品"Springboot+微服务架构指南",理论与实战结合,双管齐下! 有幸从一位朋友那里得到Alibaba内部出品强推的"SpringBoot ...

  4. 快速搭建 SpringCloud 微服务开发环境的脚手架

    快速搭建 SpringCloud 微服务开发环境的脚手架 本文作者:HelloGitHub-秦人 本文适合有 SpringBoot 和 SpringCloud 基础知识的人群,跟着本文可使用和快速搭建 ...

  5. Springboot+MySQL+VUE实现的在线教育网站源码+视频教程(Springboot微服务架构)

    下载地址:https://download.csdn.net/download/BSDKT/85347133?spm=1001.2014.3001.5503 项目介绍: Springboot+MySQ ...

  6. docker入门,镜像,容器,数据卷,dockerfile,docker网络,springboot微服务打包docker镜像[狂神yyds]

    docker学习大纲 docker概述 docker安装 docker命令 镜像命令 容器命令 操作命令 - docker镜像 容器数据卷 dockerfile docker网络原理 IDEA整合do ...

  7. SpringBoot微服务架构下的MVC模型总结

    SpringBoot微服务架构下的MVC模型产生的原因: 微服务概念改变着软件开发领域,传统的开源框架结构开发,由于其繁琐的配置流程 , 复杂的设置行为,为项目的开发增加了繁重的工作量,微服务致力于解 ...

  8. Java微服务开发流程及详细案例

    微服务开发流程及详细案例 文章目录 微服务开发流程及详细案例 一. 微服务示例简介 二. IDEA创建父Maven工程及子项目 2.1 使用IDEA创建Maven项目 2.2创建子项目模块 2.3父项 ...

  9. SpringBoot微服务框架概述

    SpringBoot微服务框架 2. Spring Boot 微服务框架的特点 3. Spring Boot 应用场景 4. SpringBoot的第一个应用 5. Springboot引导类的mai ...

最新文章

  1. python launcher怎么使用_QMUI实战(一)—为何我们要使用 LauncherActivity?
  2. 不用任何数学方法,如何计算圆面积
  3. KB244036_PXE 客户端、DHCP 和 RIS 服务器之间的 PXE 交互过程说明
  4. PSP DAILY软件功能说明书
  5. 程序员——令人喷饭的代码注释
  6. 算法 --- 二叉树的最大深度
  7. DTCC 2020 | 阿里云梁高中:DAS之基于Workload的全局自动优化实践
  8. APP、智能设备、平台账号等信息系统,实现无密码登录的可行性方案。
  9. java Comparable和Comaprator的对比
  10. 我想参加计算机俱乐部用英文翻译,加入音乐俱乐部的英文怎么写_我参加音乐俱乐部已经两年了。用英语咋说...
  11. //5. 有若干本图书,图书信息包括图书书名、作者、出版社和价格。要求输出图书价格(const成员函数), //显示图书书名、作者、出版社(非const成员函数)、根据图书书名查找图书并显示相关信息等
  12. Java 代码分享(第4篇),绘制迷宫2 绘制起点终点和路径
  13. 毛星云opencv之10.1.5综合示例--harris角点检测和绘制
  14. x-ray社区版简单使用教程
  15. 国外公司 职位及职能描述(一)
  16. 换位思考:辅导员与学生
  17. pagehelper浅见
  18. 【问底】王帅:深入PHP内核(一)——弱类型变量原理探究
  19. NOR FLASH工作原理
  20. 数据结构题库知识点汇总

热门文章

  1. RHEL 7中防火墙的配置和使用
  2. 记一次 AXI -id debug
  3. WCF热带鱼书学习手记 - ABC
  4. Linux命令 lsof -i:端口号 ——有什么用途
  5. Python 语言 Hello world
  6. 对于当前时点不能进行事物的事后确认。
  7. 关于如何提高代码执行效率。
  8. oracle数据库导入表空间,oracle数据库表空间创建导入导出
  9. Android开发中遇到的问题(四)——Android中WARNING: Application does not specify an API level requirement!的解决方法
  10. 怎么解决VMware“该虚拟机似乎正在使用中”问题