spring boot 页面boot shiro 怎么将页面值传入

&&&&spring boot与shiro集成demo
spring boot与shiro集成demo
spring boot与shiro集成demo,maven工程,简单的一个demo,文档请参考博文
若举报审核通过,可奖励20下载分
被举报人:
qiuqiupeng
举报的资源分:
请选择类型
资源无法下载
资源无法使用
标题与实际内容不符
含有危害国家安全内容
含有反动色情等内容
含广告内容
版权问题,侵犯个人或公司的版权
*详细原因:
VIP下载&&免积分60元/年(1200次)
您可能还需要
开发技术下载排行SpringMVC+Shiro权限管理 _冰个人博客_个人博客_程序猿博客
选择比努力更重要!
SpringMVC+Shiro权限管理
阅读(1590)
转载请注明:http://www.bdtool.net/blog_458.html
Design by 冰实际上在Spring boot里用Spring Security最合适,毕竟是自家东西,最重要的一点是Spring Security里自带有csrf filter,防止csrf攻击,shiro里就没有。
但是Spring Security有点太复杂,custmize起来比较费力,不如shiro来的简单。
如果想要在Spring boot里使用shiro,需要进行以下配置,首先pom.xml里要添加shiro的依赖。
&dependency&
&groupId&org.apache.shiro&/groupId&
&artifactId&shiro-spring&/artifactId&
&version&1.2.5&/version&
&/dependency&
&dependency&
&groupId&org.apache.shiro&/groupId&
&artifactId&shiro-ehcache&/artifactId&
&version&1.2.5&/version&
&/dependency&
&dependency&
&groupId&com.github.theborakompanioni&/groupId&
&artifactId&thymeleaf-extras-shiro&/artifactId&
&version&1.2.1&/version&
&/dependency&
shiro官方只提供了jsp的标签,没有提供thymeleaf的,而thymeleaf在spring boot里应用已经很广泛了,这里依赖了一个第三方包。
然后就是shiro的配置文件,这里我们使用java-based 配置
@Configuration
public class ShiroConfiguration {
@Bean(name = &lifecycleBeanPostProcessor&)
public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
return new LifecycleBeanPostProcessor();
@Bean(name = &hashedCredentialsMatcher&)
public HashedCredentialsMatcher hashedCredentialsMatcher() {
HashedCredentialsMatcher credentialsMatcher = new HashedCredentialsMatcher();
credentialsMatcher.setHashAlgorithmName(&MD5&);
credentialsMatcher.setHashIterations(2);
credentialsMatcher.setStoredCredentialsHexEncoded(true);
return credentialsM
@Bean(name = &shiroRealm&)
@DependsOn(&lifecycleBeanPostProcessor&)
public ShiroRealm shiroRealm() {
ShiroRealm realm = new ShiroRealm();
realm.setCredentialsMatcher(hashedCredentialsMatcher());
@Bean(name = &ehCacheManager&)
@DependsOn(&lifecycleBeanPostProcessor&)
public EhCacheManager ehCacheManager(){
EhCacheManager ehCacheManager = new EhCacheManager();
return ehCacheM
@Bean(name = &securityManager&)
public SecurityManager securityManager(){
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
securityManager.setRealm(shiroRealm());
securityManager.setCacheManager(ehCacheManager());
return securityM
@Bean(name = &shiroFilter&)
public ShiroFilterFactoryBean shiroFilterFactoryBean(){
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
shiroFilterFactoryBean.setSecurityManager(securityManager());
Map&String, Filter& filters = new LinkedHashMap&String, Filter&();
LogoutFilter logoutFilter = new LogoutFilter();
logoutFilter.setRedirectUrl(&/login&);
filters.put(&logout&, logoutFilter);
shiroFilterFactoryBean.setFilters(filters);
Map&String, String& filterChainDefinitionManager = new LinkedHashMap&String, String&();
filterChainDefinitionManager.put(&/logout&, &logout&);
filterChainDefinitionManager.put(&/user/**&, &authc,roles[user]&);
filterChainDefinitionManager.put(&/shop/**&, &authc,roles[shop]&);
filterChainDefinitionManager.put(&/admin/**&, &authc,roles[admin]&);
filterChainDefinitionManager.put(&/**&, &anon&);
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionManager);
shiroFilterFactoryBean.setLoginUrl(&/login&);
shiroFilterFactoryBean.setSuccessUrl(&/&);
shiroFilterFactoryBean.setUnauthorizedUrl(&/403&);
return shiroFilterFactoryB
@ConditionalOnMissingBean
public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
DefaultAdvisorAutoProxyCreator daap = new DefaultAdvisorAutoProxyCreator();
daap.setProxyTargetClass(true);
public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor() {
AuthorizationAttributeSourceAdvisor aasa = new AuthorizationAttributeSourceAdvisor();
aasa.setSecurityManager(securityManager());
@Bean(name = &shiroDialect&)
public ShiroDialect shiroDialect(){
return new ShiroDialect();
LifecycleBeanPostProcessor,这是个DestructionAwareBeanPostProcessor的子类,负责org.apache.shiro.util.Initializable类型bean的生命周期的,初始化和销毁。主要是AuthorizingRealm类的子类,以及EhCacheManager类。
HashedCredentialsMatcher,这个类是为了对密码进行编码的,防止密码在数据库里明码保存,当然在登陆认证的生活,这个类也负责对form里输入的密码进行编码。
ShiroRealm,这是个自定义的认证类,继承自AuthorizingRealm,负责用户的认证和权限的处理,可以参考JdbcRealm的实现。
EhCacheManager,缓存管理,用户登陆成功后,把用户信息和权限信息缓存起来,然后每次用户请求时,放入用户的session中,如果不设置这个bean,每个请求都会查询一次数据库。
SecurityManager,权限管理,这个类组合了登陆,登出,权限,session的处理,是个比较重要的类。
ShiroFilterFactoryBean,是个factorybean,为了生成ShiroFilter。它主要保持了三项数据,securityManager,filters,filterChainDefinitionManager。
DefaultAdvisorAutoProxyCreator,Spring的一个bean,由Advisor决定对哪些类的方法进行AOP代理。
AuthorizationAttributeSourceAdvisor,shiro里实现的Advisor类,内部使用AopAllianceAnnotationsAuthorizingMethodInterceptor来拦截用以下注解的方法。老实说,这里注入securityManager,我不知道有啥用,从source上看不出它在什么地方会被调用。
private static final Class&? extends Annotation&[] AUTHZ_ANNOTATION_CLASSES =
new Class[] {
RequiresPermissions.class, RequiresRoles.class,
RequiresUser.class, RequiresGuest.class, RequiresAuthentication.class
9.ShiroDialect,为了在thymeleaf里使用shiro的标签的bean
相关 [apache shiro spring] 推荐:
- 企业架构 - ITeye博客
实际上在Spring boot里用Spring Security最合适,毕竟是自家东西,最重要的一点是Spring Security里自带有csrf filter,防止csrf攻击,shiro里就没有. 但是Spring Security有点太复杂,custmize起来比较费力,不如shiro来的简单.
- CSDN博客推荐文章
什么是Apache Shiro?. Apache shiro 是一个强大而灵活的开源安全框架,可清晰地处理身份认证、授权、会话(session)和加密. Apache Shiro最主要的初衷是为了易用和易理解,处理安全问题可能非常复杂甚至非常痛苦,但并非一定要如此. 一个框架应该尽可能地将复杂的问题隐藏起来,提供清晰直观的API使开发者可以很轻松地开发自己的程序安全代码.
- Web前端 - ITeye博客
Apache Shiro是什么. Apache Shiro是一个功能强大且易于使用的Java安全框架,进行认证,授权,加密和会话管理. 随着Shiro的易于理解的API,你可以快速,轻松地确保任何应用程序 - 移动应用从最小的到最大的Web和企业应用. 如何使用Apache Shiro(这里指与Spring 集成).
- 开源软件 - ITeye博客
第一部分 Shiro构架介绍. Apache Shiro是一个强大易用的Java安全框架,提供了认证、授权、加密和会话管理等功能: . 认证 - 用户身份识别,常被称为用户“登录”;. 密码加密 - 保护或隐藏数据防止被偷窥;. 会话管理 - 每用户相关的时间敏感的状态.
对于任何一个应用程序,Shiro都可以提供全面的安全管理服务.
- 企业架构 - ITeye博客
Apache Shiro 是功能强大并且容易集成的开源权限框架,它能够完成认证、授权、加密、会话管理等功能. 认证和授权为权限控制的核心,简单来说,“认证”就是证明你是谁. Web 应用程序一般做法通过表单提交用户名及密码达到认证目的. “授权”即是否允许已认证用户访问受保护资源. 关于 Shiro 的一系列特征及优点,很多文章已有列举,这里不再逐一赘述,本文重点介绍 Shiro 在 Web Application 中如何实现验证码认证以及如何实现单点登录.
- CSDN博客架构设计推荐文章
shiro是权限管理框架,现在已经会利用它如何控制权限. 为了能够为多个系统提供统一认证入口,又研究了单点登录框架cas. 因为二者都会涉及到对session的管理,所以需要进行集成. Shiro在1.2.0的时候提供了对cas的集成. 因此在项目中添加shiro-cas的依赖. Shiro对cas集成后,cas
client的配置更加简单了.
- If you are thinking one year ahead, you plant rice. If you are thinking twenty years ahead, you plant trees. If you are thinking a hundred years ahead, you educate people. - BlogJava-首页技术区
开发系统中,少不了权限,目前java里的权限框架有SpringSecurity和Shiro(以前叫做jsecurity),对于SpringSecurity:功能太过强大以至于功能比较分散,使用起来也比较复杂,跟Spring结合的比较好. 对于初学Spring Security者来说,曲线还是较大,需要深入学习其源码和框架,配置起来也需要费比较大的力气,扩展性也不是特别强.
- 互联网 - ITeye博客
shiro与CAS集成以后的单点退出. 效果任何一个应用退出以后 所有应用都要重新登录. 实现思路shiro退出系统以后重新定向到cas的退出. 1.重新配置shiro的登出跳转.
shiro退出以后跳转到cas的退出.
cas退出以后通过service参数跳转回应用界面. 2.覆盖shiro的默认退出实现 .
- CSDN博客推荐文章
昨天,我在《
Shiro系列之Shiro+Mysql实现用户认证(Authentication)》中简单介绍了使用Shiro+Mysql实现用户认证的功能,今天我们继续使用其中的示例,讲解一下如何实现用户授权. 所谓授权,就是判断当前用户具体哪些权限,能够执行哪些操作,或是访问哪些资源(Web中的URL,又或是页面上的一个按钮,一个编辑框等都可以视为资源).
- CSDN博客推荐文章
网上大多数介绍Apache Shiro的资料都是使用ini文件的简单配置为例,很少用讲到如何配合数据库来实现用户认证的. 我也是刚刚开始接触Shiro,在这里介绍一个入门级别的Shiro+Mysql的配置方法,这个方法仅仅是个开始,并没有和Web,Spring,Mybatis等框架进行整合,后续我还会继续和大家分享我的学习过程及心得.
坚持分享优质有趣的原创文章,并保留作者信息和版权声明,任何问题请联系:@。springBoot(27)
shiro使用FormAuthenticationFilter进行表单认证,验证校验的功能应该加在FormAuthenticationFilter中,在认证之前进行验证码校验。
需要写FormAuthenticationFilter的子类,继承FormAuthenticationFilter,改写它的认证方法,在认证之前进行验证码校验。
自定义FormAuthenticationFilter
package com.example.config.
import javax.servlet.ServletR
import javax.servlet.ServletR
import javax.servlet.http.HttpServletR
import javax.servlet.http.HttpS
import org.apache.shiro.web.filter.authc.FormAuthenticationF
public class CustomFormAuthenticationFilter extends FormAuthenticationFilter{
protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
// 在这里进行验证码的校验
HttpServletRequest httpServletRequest = (HttpServletRequest)
HttpSession session = httpServletRequest.getSession();
// 取出验证码
String validateCode = (String) session.getAttribute(&validateCode&);
// 取出页面的验证码
// 输入的验证和session中的验证进行对比
String randomcode = httpServletRequest.getParameter(&randomcode&);
if (randomcode != null && validateCode != null && !randomcode.equals(validateCode)) {
// 如果校验失败,将验证码错误失败信息,通过shiroLoginFailure设置到request中
httpServletRequest.setAttribute(&shiroLoginFailure&, &kaptchaValidateFailed&);//自定义登录异常
// 拒绝访问,不再校验账号和密码
return super.onAccessDenied(request, response);
在ShiroConfiguration.java中的shiroFilter方法注入自定义FormAuthenticationFilter
public ShiroFilterFactoryBean shiroFilter(SecurityManager securityManager) {
System.out.println(&ShiroConfiguration.shiroFilter()&);
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
Map&String, Filter& filters = shiroFilterFactoryBean.getFilters();//获取filters
filters.put(&authc&, new CustomFormAuthenticationFilter());//将自定义 的FormAuthenticationFilter注入shiroFilter中
// 必须设置SecuritManager
shiroFilterFactoryBean.setSecurityManager(securityManager);
Map&String, String& filterChainDefinitionMap = new LinkedHashMap&String, String&();
// 配置退出过滤器,其中的具体代码Shiro已经替我们实现了
filterChainDefinitionMap.put(&/logout&, &logout&);
//验证码可以匿名访问
filterChainDefinitionMap.put(&/validatecodeServlet&, &anon&);
//配置记住我或认证通过可以访问的地址
filterChainDefinitionMap.put(&/index&, &user&);
filterChainDefinitionMap.put(&/&, &user&);
// &!-- 过滤链定义,从上向下顺序执行,一般将 /**放在最为下边 --&:这是一个坑呢,一不小心代码就不好使了;
// &!-- authc:所有url都必须认证通过才可以访问; anon:所有url都都可以匿名访问--&
filterChainDefinitionMap.put(&/**&, &authc&);
// 如果不设置默认会自动寻找Web工程根目录下的&/login.jsp&页面
shiroFilterFactoryBean.setLoginUrl(&/login&);
// 登录成功后要跳转的链接
shiroFilterFactoryBean.setSuccessUrl(&/index&);
// 未授权界面;
shiroFilterFactoryBean.setUnauthorizedUrl(&/403&);
shiroFilterFactoryBean
.setFilterChainDefinitionMap(filterChainDefinitionMap);
return shiroFilterFactoryB
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
Map&String, Filter& filters = shiroFilterFactoryBean.getFilters();//获取filters
filters.put(&authc&, new CustomFormAuthenticationFilter());//将自定义 的FormAuthenticationFilter注入shiroFilter中 &
登录方法加入自定义的异常kaptchaValidateFailed
@RequestMapping(value = &/login&, method = RequestMethod.POST)
public String login(HttpServletRequest request, Map&String, Object& map) {
System.out.println(&HomeController.login&);
// 登录失败从request中获取shiro处理的异常信息
// shiroLoginFailure:就是shiro异常类的全类名
String exception = (String) request.getAttribute(&shiroLoginFailure&);
String msg = &&;
if (exception != null) {
if (UnknownAccountException.class.getName().equals(exception)) {
System.out.println(&UnknownAccountException --&帐号不存在:&);
msg = &UnknownAccountException --&帐号不存在:&;
} else if (IncorrectCredentialsException.class.getName().equals(exception)) {
System.out.println(&IncorrectCredentialsException -- & 密码不正确:&);
msg = &IncorrectCredentialsException -- & 密码不正确:&;
} else if (&kaptchaValidateFailed&.equals(exception)) {
System.out.println(&kaptchaValidateFailed -- & 验证码错误&);
msg = &kaptchaValidateFailed -- & 验证码错误&;
msg = &else && & +
System.out.println(&else -- && + exception);
map.put(&msg&, msg);
// 此方法不处理登录成功,由shiro进行处理.
return &/login&;
login.html
&!DOCTYPE html&
&html xmlns=&http://www.w3.org/1999/xhtml& xmlns:th=&http://www.thymeleaf.org&
xmlns:sec=&http://www.thymeleaf.org/thymeleaf-extras-springsecurity3&&
&meta charset=&UTF-8& /&
&title&Insert title here&/title&
错误信息:&h4 th:text=&${msg}&&&/h4&
&form action=&& method=&post&&
&p&账号:&input type=&text& name=&username& value=&admin&/&&/p&
&p&密码:&input type=&text& name=&password& value=&123456&/&&/p&
&p&验证码:&input type=&text& name=&randomcode&/&
&img th:src=&@{/validatecodeServlet}& height=&20px& width=&60px& onclick=&random(this)&/&&/p&
&P&&input type=&checkbox& name=&rememberMe& /&记住我&/P&
&p&&input type=&submit& value=&登录&/&&/p&
&script th:inline=&javascript&&
function random(tmp){
tmp.src=&/validatecodeServlet?rnd=&+Math.random();
验证码Servlet
package com.example.
import java.awt.C
import java.awt.F
import java.awt.G
import java.awt.image.BufferedI
import java.io.IOE
import java.io.OutputS
import java.util.R
import javax.imageio.ImageIO;
import javax.servlet.ServletE
import javax.servlet.annotation.WebS
import javax.servlet.http.HttpS
import javax.servlet.http.HttpServletR
import javax.servlet.http.HttpServletR
import javax.servlet.http.HttpS
@WebServlet(urlPatterns=&/validatecodeServlet&)
public class ValidatecodeServlet extends HttpServlet{
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println(&&&&&&&&&&&doGet()&&&&&&&&&&&&);
doPost(req, resp);
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println(&&&&&&&&&&&doPost()&&&&&&&&&&&&);
int width = 60;
int height = 32;
//create the image
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
Graphics g = image.getGraphics();
// set the background color
g.setColor(new Color(0xDCDCDC));
g.fillRect(0, 0, width, height);
// draw the border
g.setColor(Color.black);
g.drawRect(0, 0, width - 1, height - 1);
// create a random instance to generate the codes
Random rdm = new Random();
String hash1 = Integer.toHexString(rdm.nextInt());
System.out.print(hash1);
// make some confusion
for (int i = 0; i & 50; i++) {
int x = rdm.nextInt(width);
int y = rdm.nextInt(height);
g.drawOval(x, y, 0, 0);
// generate a random code
String capstr = hash1.substring(0, 4);
HttpSession session = req.getSession(true);
//将生成的验证码存入session
session.setAttribute(&validateCode&, capstr);
g.setColor(new Color(0, 100, 0));
g.setFont(new Font(&Candara&, Font.BOLD, 24));
g.drawString(capstr, 8, 24);
g.dispose();
//输出图片
resp.setContentType(&image/jpeg&);
OutputStream strm = resp.getOutputStream();
ImageIO.write(image, &jpeg&, strm);
strm.close();
Application.java
package com.
import org.springframework.boot.SpringA
import org.springframework.boot.autoconfigure.SpringBootA
import org.springframework.boot.web.servlet.ServletComponentS
@ServletComponentScan
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:11871次
排名:千里之外
转载:162篇
(9)(25)(7)(21)(34)(49)(18)12475人阅读
Spring(31)
本来是打算接着写关于数据库方面,集成MyBatis的,刚好赶上朋友问到Shiro权限管理,就先总结下发出来了。
使用Shiro之前用在Spring MVC中,是通过XML文件进行配置。
既然现在在写Spring Boot的帖子,就将Shiro应用到Spring Boot中,我本地已经完成了SpringBoot使用Shiro的实例,将配置方法共享一下。
先简单介绍一下Shiro,对于没有用过Shiro的朋友,也算是做个简介吧。
Shiro是Apache下的一个开源项目,我们称之为Apache Shiro。它是一个很易用与Java项目的的安全框架,提供了认证、授权、加密、会话管理,与 Spring Security 一样都是做一个权限的安全框架,但是与Spring Security 相比,在于 Shiro 使用了比较简单易懂易于使用的授权方式。
Apache Shiro 的三大核心组件
- Subject 当前用户操作
- SecurityManager 用于管理所有的Subject
- Realms 用于进行权限信息的验证,也是我们需要自己实现的。
我们需要实现Realms的Authentication 和 Authorization。其中 Authentication 是用来验证用户身份,Authorization 是授权访问控制,用于对用户进行的操作授权,证明该用户是否允许进行当前操作,如访问某个链接,某个资源文件等。
Apache Shiro 核心通过 Filter 来实现,就好像SpringMvc 通过DispachServlet 来主控制一样。
既然是使用 Filter 一般也就能猜到,是通过URL规则来进行过滤和权限校验,所以我们需要定义一系列关于URL的规则和访问权限。
另外我们可以通过Shiro 提供的会话管理来获取Session中的信息。Shiro 也提供了缓存支持,使用 CacheManager 来管理。
官方网站:
完整架构图:
下面我们通过代码实战来看下Spring Boot 中应用Shiro:
1、创建数据库表
--------------
----------
----------
看截图,上面3张表是我测试别的用的,可以忽略。
下面是,数据库脚本和测试数据。
CREATE DATABASE /*!32312 IF NOT EXISTS*/`test` /*!40100 DEFAULT CHARACTER SET utf8 */;
USE `test`;
DROP TABLE IF EXISTS `t_permission`;
CREATE TABLE `t_permission` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`permissionname` varchar(32) DEFAULT NULL,
`role_id` int(11) DEFAULT NULL,
KEY `id` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8;
into `t_permission`(`id`,`permissionname`,`role_id`) values (1,'add',2),(2,'del',1),(3,'update',2),(4,'query',3),(5,'user:query',1),(6,'user:edit',2);
DROP TABLE IF EXISTS `t_role`;
CREATE TABLE `t_role` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`rolename` varchar(32) DEFAULT NULL,
KEY `id` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;
into `t_role`(`id`,`rolename`) values (1,'admin'),(2,'manager'),(3,'normal');
DROP TABLE IF EXISTS `t_user`;
CREATE TABLE `t_user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(32) DEFAULT NULL,
`password` varchar(32) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;
into `t_user`(`id`,`username`,`password`) values (1,'tom','123456'),(2,'jack','123456'),(3,'rose','123456');
DROP TABLE IF EXISTS `t_user_role`;
CREATE TABLE `t_user_role` (
`user_id` int(11) DEFAULT NULL,
`role_id` int(11) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
into `t_user_role`(`user_id`,`role_id`) values (1,1),(1,3),(2,2),(2,3),(3,3);
2、创建对应实体类
package org.springboot.sample.
import java.util.HashS
import java.util.L
import java.util.S
import javax.persistence.E
import javax.persistence.FetchT
import javax.persistence.GeneratedV
import javax.persistence.GenerationT
import javax.persistence.Id;
import javax.persistence.JoinC
import javax.persistence.JoinT
import javax.persistence.ManyToM
import javax.persistence.T
import javax.persistence.T
import org.hibernate.validator.constraints.NotE
* 单红宇()
* http://blog.csdn.net/catoop/
@Table(name = "t_user")
public class User {
@GeneratedValue(strategy = GenerationType.IDENTITY)
@NotEmpty(message = "用户名不能为空")
@NotEmpty(message = "密码不能为空")
@ManyToMany(fetch=FetchType.EAGER)
@JoinTable(name = "t_user_role", joinColumns = { @JoinColumn(name = "user_id") }, inverseJoinColumns = {
@JoinColumn(name = "role_id") })
private List&Role& roleL
public User() {
public User(String username, String password) {
this.username =
this.password =
@Transient
public Set&String& getRolesName() {
List&Role& roles = getRoleList();
Set&String& set = new HashSet&String&();
for (Role role : roles) {
set.add(role.getRolename());
package org.springboot.sample.
import java.util.ArrayL
import java.util.L
import javax.persistence.E
import javax.persistence.FetchT
import javax.persistence.GeneratedV
import javax.persistence.GenerationT
import javax.persistence.Id;
import javax.persistence.JoinC
import javax.persistence.JoinT
import javax.persistence.ManyToM
import javax.persistence.OneToM
import javax.persistence.T
import javax.persistence.T
* 角色(管理员,普通用户等)
http://blog.csdn.net/catoop/
@Table(name = "t_role")
public class Role {
@GeneratedValue(strategy = GenerationType.IDENTITY)
@OneToMany(mappedBy = "role", fetch=FetchType.EAGER)
private List&Permission& permissionL
@ManyToMany
@JoinTable(name = "t_user_role", joinColumns = { @JoinColumn(name = "role_id") }, inverseJoinColumns = {
@JoinColumn(name = "user_id") })
private List&User& userL
@Transient
public List&String& getPermissionsName() {
List&String& list = new ArrayList&String&();
List&Permission& perlist = getPermissionList();
for (Permission per : perlist) {
list.add(per.getPermissionname());
Permission.java
package org.springboot.sample.
import javax.persistence.E
import javax.persistence.GeneratedV
import javax.persistence.GenerationT
import javax.persistence.Id;
import javax.persistence.JoinC
import javax.persistence.ManyToO
import javax.persistence.T
* 权限(增删改查等)
* 单红宇()
* http://blog.csdn.net/catoop/
@Table(name = "t_permission")
public class Permission {
@GeneratedValue(strategy = GenerationType.IDENTITY)
@ManyToOne
@JoinColumn(name = "role_id")
3、Shiro 配置,相当于SpringMVC 中的XML配置
ShiroConfiguration.java
package org.springboot.sample.
import java.util.LinkedHashM
import java.util.M
import org.apache.shiro.cache.ehcache.EhCacheM
import org.apache.shiro.spring.LifecycleBeanPostP
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceA
import org.apache.shiro.spring.web.ShiroFilterFactoryB
import org.apache.shiro.web.mgt.DefaultWebSecurityM
import org.slf4j.L
import org.slf4j.LoggerF
import org.springboot.sample.dao.IScoreD
import org.springboot.sample.security.MyShiroR
import org.springboot.sample.service.StudentS
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyC
import org.springframework.boot.context.embedded.FilterRegistrationB
import org.springframework.context.annotation.B
import org.springframework.context.annotation.C
import org.springframework.web.filter.DelegatingFilterP
* Shiro 配置
http://blog.csdn.net/catoop/
@Configuration
public class ShiroConfiguration {
private static final Logger logger = LoggerFactory.getLogger(ShiroConfiguration.class);
public EhCacheManager getEhCacheManager() {
EhCacheManager em = new EhCacheManager();
em.setCacheManagerConfigFile("classpath:ehcache-shiro.xml");
@Bean(name = "myShiroRealm")
public MyShiroRealm myShiroRealm(EhCacheManager cacheManager) {
MyShiroRealm realm = new MyShiroRealm();
realm.setCacheManager(cacheManager);
* 注册DelegatingFilterProxy(Shiro)
* 集成Shiro有2种方法:
* 1. 按这个方法自己组装一个FilterRegistrationBean(这种方法更为灵活,可以自己定义UrlPattern,
* 在项目使用中你可能会因为一些很但疼的问题最后采用它, 想使用它你可能需要看官网或者已经很了解Shiro的处理原理了)
* 2. 直接使用ShiroFilterFactoryBean(这种方法比较简单,其内部对ShiroFilter做了组装工作,无法自己定义UrlPattern,
* 默认拦截 /*)
* dispatcherServlet
@Bean(name = "lifecycleBeanPostProcessor")
public LifecycleBeanPostProcessor getLifecycleBeanPostProcessor() {
return new LifecycleBeanPostProcessor();
public DefaultAdvisorAutoProxyCreator getDefaultAdvisorAutoProxyCreator() {
DefaultAdvisorAutoProxyCreator daap = new DefaultAdvisorAutoProxyCreator();
daap.setProxyTargetClass(true);
@Bean(name = "securityManager")
public DefaultWebSecurityManager getDefaultWebSecurityManager(MyShiroRealm myShiroRealm) {
DefaultWebSecurityManager dwsm = new DefaultWebSecurityManager();
dwsm.setRealm(myShiroRealm);
dwsm.setCacheManager(getEhCacheManager());
public AuthorizationAttributeSourceAdvisor getAuthorizationAttributeSourceAdvisor(DefaultWebSecurityManager securityManager) {
AuthorizationAttributeSourceAdvisor aasa = new AuthorizationAttributeSourceAdvisor();
aasa.setSecurityManager(securityManager);
* 加载shiroFilter权限控制规则(从数据库读取然后配置)
private void loadShiroFilterChain(ShiroFilterFactoryBean shiroFilterFactoryBean, StudentService stuService, IScoreDao scoreDao){
Map&String, String& filterChainDefinitionMap = new LinkedHashMap&String, String&();
filterChainDefinitionMap.put("/user", "authc");
("##################从数据库读取权限规则,加载到shiroFilter中##################");
filterChainDefinitionMap.put("/user/edit/**", "authc,perms[user:edit]");
filterChainDefinitionMap.put("/login", "anon");
filterChainDefinitionMap.put("/**", "anon");
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
* ShiroFilter&br/&
* 注意这里参数中的 StudentService 和 IScoreDao 只是一个例子,因为我们在这里可以用这样的方式获取到相关访问数据库的对象,
* 然后读取数据库相关配置,配置到 shiroFilterFactoryBean 的访问规则中。实际项目中,请使用自己的Service来处理业务逻辑。
* myShiroRealm
* stuService
* scoreDao
@Bean(name = "shiroFilter")
public ShiroFilterFactoryBean getShiroFilterFactoryBean(DefaultWebSecurityManager securityManager, StudentService stuService, IScoreDao scoreDao) {
ShiroFilterFactoryBean shiroFilterFactoryBean = new MShiroFilterFactoryBean();
shiroFilterFactoryBean.setSecurityManager(securityManager);
shiroFilterFactoryBean.setLoginUrl("/login");
shiroFilterFactoryBean.setSuccessUrl("/user");
shiroFilterFactoryBean.setUnauthorizedUrl("/403");
loadShiroFilterChain(shiroFilterFactoryBean, stuService, scoreDao);
return shiroFilterFactoryB
* 继承 ShiroFilterFactoryBean 处理拦截资源文件问题。
http://blog.csdn.net/catoop/
public class MShiroFilterFactoryBean extends ShiroFilterFactoryBean {
private Set&String& ignoreE
public MShiroFilterFactoryBean() {
ignoreExt = new HashSet&&();
ignoreExt.add(".jpg");
ignoreExt.add(".png");
ignoreExt.add(".gif");
ignoreExt.add(".bmp");
ignoreExt.add(".js");
ignoreExt.add(".css");
protected AbstractShiroFilter createInstance() throws Exception {
SecurityManager securityManager = getSecurityManager();
if (securityManager == null) {
String msg = "SecurityManager property must be set.";
throw new BeanInitializationException(msg);
if (!(securityManager instanceof WebSecurityManager)) {
String msg = "The security manager does not implement the WebSecurityManager interface.";
throw new BeanInitializationException(msg);
FilterChainManager manager = createFilterChainManager();
PathMatchingFilterChainResolver chainResolver = new PathMatchingFilterChainResolver();
chainResolver.setFilterChainManager(manager);
return new MSpringShiroFilter((WebSecurityManager) securityManager, chainResolver);
private final class MSpringShiroFilter extends AbstractShiroFilter {
protected MSpringShiroFilter(WebSecurityManager webSecurityManager, FilterChainResolver resolver) {
if (webSecurityManager == null) {
throw new IllegalArgumentException("WebSecurityManager property cannot be null.");
setSecurityManager(webSecurityManager);
if (resolver != null) {
setFilterChainResolver(resolver);
protected void doFilterInternal(ServletRequest servletRequest, ServletResponse servletResponse,
FilterChain chain) throws ServletException, IOException {
HttpServletRequest request = (HttpServletRequest)servletR
String str = request.getRequestURI().toLowerCase();
boolean flag = true;
int idx = 0;
if(( idx = str.indexOf(".")) & 0){
str = str.substring(idx);
if(ignoreExt.contains(str.toLowerCase()))
flag = false;
super.doFilterInternal(servletRequest, servletResponse, chain);
chain.doFilter(servletRequest, servletResponse);
其中的 ehcache-shiro.xml 在 src/main/resources 下面,内容为:
&?xml version="1.0" encoding="UTF-8"?&
updateCheck="false" name="shiroCache"&
maxElementsInMemory="10000"
eternal="false"
timeToIdleSeconds="120"
timeToLiveSeconds="120"
overflowToDisk="false"
diskPersistent="false"
diskExpiryThreadIntervalSeconds="120"
4、继承 AuthorizingRealm 实现认证和授权2个方法
MyShiroRealm.java
package org.springboot.sample.
import java.util.L
import mons.lang3.builder.ReflectionToStringB
import mons.lang3.builder.ToStringS
import org.apache.shiro.authc.AuthenticationE
import org.apache.shiro.authc.AuthenticationI
import org.apache.shiro.authc.AuthenticationT
import org.apache.shiro.authc.SimpleAuthenticationI
import org.apache.shiro.authc.UsernamePasswordT
import org.apache.shiro.authz.AuthorizationI
import org.apache.shiro.authz.SimpleAuthorizationI
import org.apache.shiro.realm.AuthorizingR
import org.apache.shiro.subject.PrincipalC
import org.slf4j.L
import org.slf4j.LoggerF
import org.springboot.sample.dao.IUserD
import org.springboot.sample.entity.R
import org.springboot.sample.entity.U
import org.springframework.beans.factory.annotation.A
import org.springframework.stereotype.S
import org.springframework.transaction.annotation.T
* MyShiroRealm
http://blog.csdn.net/catoop/
public class MyShiroRealm extends AuthorizingRealm{
private static final Logger logger = LoggerFactory.getLogger(MyShiroRealm.class);
@Autowired
private IUserDao userD
* 权限认证,为当前登录的Subject授予角色和权限
* 经测试:本例中该方法的调用时机为需授权资源被访问时
* 经测试:并且每次访问需授权资源时都会执行该方法中的逻辑,这表明本例中默认并未启用AuthorizationCache
* 经测试:如果连续访问同一个URL(比如刷新),该方法不会被重复调用,Shiro有一个时间间隔(也就是cache时间,在ehcache-shiro.xml中配置),超过这个时间间隔再刷新页面,该方法会被执行
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
("##################执行Shiro权限认证##################");
String loginName = (String)super.getAvailablePrincipal(principalCollection);
User user=userDao.findByName(loginName);
if(user!=null){
SimpleAuthorizationInfo info=new SimpleAuthorizationInfo();
info.setRoles(user.getRolesName());
List&Role& roleList=user.getRoleList();
for (Role role : roleList) {
info.addStringPermissions(role.getPermissionsName());
return null;
* 登录认证
protected AuthenticationInfo doGetAuthenticationInfo(
AuthenticationToken authenticationToken) throws AuthenticationException {
UsernamePasswordToken token=(UsernamePasswordToken) authenticationT
("验证当前Subject时获取到token为:" + ReflectionToStringBuilder.toString(token, ToStringStyle.MULTI_LINE_STYLE));
User user=userDao.findByName(token.getUsername());
if(user!=null){
return new SimpleAuthenticationInfo(user.getUsername(), user.getPassword(), getName());
return null;
注意:其中 userDao.findByName 这个代码就不贴上了,也没啥可贴的,根据姓名查询一个对象而已。
5、编写测试的 Controller 和测试 jsp 页面
ShiroController.java
package org.springboot.sample.controller
import java.util.Map
import javax.validation.Valid
import org.apache.shiro.SecurityUtils
import org.apache.shiro.authc.AuthenticationException
import org.apache.shiro.authc.ExcessiveAttemptsException
import org.apache.shiro.authc.IncorrectCredentialsException
import org.apache.shiro.authc.LockedAccountException
import org.apache.shiro.authc.UnknownAccountException
import org.apache.shiro.authc.UsernamePasswordToken
import org.apache.shiro.subject.Subject
import org.slf4j.Logger
import org.slf4j.LoggerFactory
import org.springboot.sample.dao.IUserDao
import org.springboot.sample.entity.User
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.stereotype.Controller
import org.springframework.ui.Model
import org.springframework.validation.BindingResult
import org.springframework.web.bind.annotation.PathVariable
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RequestMethod
import org.springframework.web.servlet.mvc.support.RedirectAttributes
@Controller
public class ShiroController {
private static final Logger logger = LoggerFactory.getLogger(ShiroController.class)
@Autowired
private IUserDao userDao
@RequestMapping(value="/login",method=RequestMethod.GET)
public String loginForm(Model model){
model.addAttribute("user", new User())
return "login"
@RequestMapping(value="/login",method=RequestMethod.POST)
public String login(@Valid User user,BindingResult bindingResult,RedirectAttributes redirectAttributes){
if(bindingResult.hasErrors()){
return "login"
String username = user.getUsername()
UsernamePasswordToken token = new UsernamePasswordToken(user.getUsername(), user.getPassword())
//获取当前的Subject
Subject currentUser = SecurityUtils.getSubject()
//在调用了login方法后,SecurityManager会收到AuthenticationToken,并将其发送给已配置的Realm执行必须的认证检查
//每个Realm都能在必要时对提交的AuthenticationTokens作出反应
//所以这一步在调用login(token)方法时,它会走到MyRealm.doGetAuthenticationInfo()方法中,具体验证方式详见此方法
logger.info("对用户[" + username + "]进行登录验证..验证开始")
currentUser.login(token)
logger.info("对用户[" + username + "]进行登录验证..验证通过")
}catch(UnknownAccountException uae){
logger.info("对用户[" + username + "]进行登录验证..验证未通过,未知账户")
redirectAttributes.addFlashAttribute("message", "未知账户")
}catch(IncorrectCredentialsException ice){
logger.info("对用户[" + username + "]进行登录验证..验证未通过,错误的凭证")
redirectAttributes.addFlashAttribute("message", "密码不正确")
}catch(LockedAccountException lae){
logger.info("对用户[" + username + "]进行登录验证..验证未通过,账户已锁定")
redirectAttributes.addFlashAttribute("message", "账户已锁定")
}catch(ExcessiveAttemptsException eae){
logger.info("对用户[" + username + "]进行登录验证..验证未通过,错误次数过多")
redirectAttributes.addFlashAttribute("message", "用户名或密码错误次数过多")
}catch(AuthenticationException ae){
//通过处理Shiro的运行时AuthenticationException就可以控制用户登录失败或密码错误时的情景
logger.info("对用户[" + username + "]进行登录验证..验证未通过,堆栈轨迹如下")
ae.printStackTrace()
redirectAttributes.addFlashAttribute("message", "用户名或密码不正确")
//验证是否登录成功
if(currentUser.isAuthenticated()){
logger.info("用户[" + username + "]登录认证通过(这里可以进行一些认证通过后的一些系统参数初始化操作)")
return "redirect:/user"
token.clear()
return "redirect:/login"
@RequestMapping(value="/logout",method=RequestMethod.GET)
public String logout(RedirectAttributes redirectAttributes ){
//使用权限管理工具进行用户的退出,跳出登录,给出提示信息
SecurityUtils.getSubject().logout()
redirectAttributes.addFlashAttribute("message", "您已安全退出")
return "redirect:/login"
@RequestMapping("/403")
public String unauthorizedRole(){
logger.info("------没有权限-------")
return "403"
@RequestMapping("/user")
public String getUserList(Map&String, Object& model){
model.put("userList", userDao.getList())
return "user"
@RequestMapping("/user/edit/{userid}")
public String getUserList(@PathVariable int userid){
logger.info("------进入用户信息修改-------")
return "user_edit"
&%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%&
&%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%&
&!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"&
&登录页面----${message }&
alt="" src="${pageContext.request.contextPath }/pic.jpg"&
action="${pageContext.request.contextPath }/login"
commandName="user" method="post"&
用户名: path="username" /&
path="username" cssClass="error" /&
密码: path="password" /&
path="password" cssClass="error" /&
name="button"&提交&
&%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%&
&%@ taglib prefix="c" uri="/jsp/jstl/core" %&
&%@ taglib prefix="shiro" uri="http://shiro.apache.org/tags" %&
&!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"&
&用户列表&
&${message }&
&用户列表-- href="${pageContext.request.contextPath }/logout"&退出登录&
&权限列表&
&用户已经登录显示此内容/&&/&
name="manager"&manager角色登录显示此内容/&&
name="admin"&admin角色登录显示此内容/&&
name="normal"&normal角色登录显示此内容/&&/&
name="manager,admin"&manager or admin 角色用户登录显示此内容/&&/&
/&-显示当前登录用户名/&/&
name="add"&add权限用户显示此内容/&&
name="user:query"&user:query权限用户显示此内容/&&
name="user:query"&不具有user:query权限的用户显示此内容 /&&
/&所有用户列表:/&
items="${userList }" var="user"&
&用户名:${user.username }----密码:${user.password }---- href="${pageContext.request.contextPath }/user/edit/${user.id}"&修改用户(测试根据不同用户可访问权限不同,本例tom无权限,jack有权限)&&
alt="" src="${pageContext.request.contextPath }/pic.jpg"&
type="text/javascript" src="${pageContext.request.contextPath }/webjarslocator/jquery/jquery.js"&&
user_edit.jsp
&%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%&
&%@ taglib prefix="c" uri="/jsp/jstl/core" %&
&%@ taglib prefix="shiro" uri="http://shiro.apache.org/tags" %&
&!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"&
&用户信息 - 修改&
&修改用户信息页面&/&
href="${pageContext.request.contextPath }/user"&返回用户列表&
&%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%&
&%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %&
&!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"&
&权限错误&
&对不起,您没有权限请求此连接!&
alt="" src="${pageContext.request.contextPath }/pic.jpg"&
其中的pic.jpg 是测试代码遗留的,没有任何用处。关于 Controller 和 JSP 页面本文不做介绍,关于Spring Boot 使用Controller 和 JSP ,前面已经有文章介绍。
启动服务后访问
会自动跳到 login 页面。
登录成功后,会打开 user 页面(关于默认登录页、成功成功URL、没有权限URL,在 ShiroConfiguration 中已经配置)。
在 user 页面上,不同用户会根据权限不同显示不同的内容,下面的修改操作也已经有文字说明,更换账号测试便知。
然后我们在实际项目中:不但要在页面上控制不同权限隐藏或将某些操作设置为不可用状态,还要在实际上控制那个操作背后的请求是真的不可以使用的。(例如:页面上的修改按钮已经灰化了,而我知道了修改按钮正常情况下点击会触发的请求,此时我直接模拟这个修改请求,应当是没有权限的才对,这样才算是真正的控制了权限。)
Filter Chain定义说明
1、一个URL可以配置多个Filter,使用逗号分隔
2、当设置多个过滤器时,全部验证通过,才视为通过
3、部分过滤器可指定参数,如perms,roles
Shiro内置的FilterChain
Filter Name
org.apache.shiro.web.filter.authc.AnonymousFilter
org.apache.shiro.web.filter.authc.FormAuthenticationFilter
authcBasic
org.apache.shiro.web.filter.authc.BasicHttpAuthenticationFilter
org.apache.shiro.web.filter.authz.PermissionsAuthorizationFilter
org.apache.shiro.web.filter.authz.PortFilter
org.apache.shiro.web.filter.authz.HttpMethodPermissionFilter
org.apache.shiro.web.filter.authz.RolesAuthorizationFilter
org.apache.shiro.web.filter.authz.SslFilter
org.apache.shiro.web.filter.authc.UserFilter
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:1464516次
积分:14902
积分:14902
排名:第515名
原创:237篇
转载:39篇
译文:10篇
评论:585条
文章:22篇
阅读:190638
(2)(10)(12)(10)(25)(17)(17)(10)(13)(21)(12)(5)(1)(9)(4)(6)(8)(2)(3)(2)(5)(2)(6)(4)(2)(1)(2)(1)(2)(1)(7)(14)(7)(5)(3)(1)(2)(19)(9)(3)

我要回帖

更多关于 spring boot 页面跳转 的文章

 

随机推荐