Springboot+shiro配置笔记+错误小结(转)
软件152 尹以操
springboot不像springmvc,它没有xml配置文件,那该如何配置shiro呢,其实也不难,用java代码+注解来解决这个问题。仅以此篇记录我对shiro的学习,如有对过客造成不便,实在抱歉!
一、加入jar包
既然要用到shiro,当然要加入它的jar包咯,在pom.xml中jar包依赖中加入:
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.2.2</version>
</dependency>
二、写实体类
这需要三个实体类,hibernate自动生成5个表
User实体(用户):

package com.cy.coo.bean; import java.util.List;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany; import com.fasterxml.jackson.annotation.JsonBackReference; @Entity
public class User {@Id</br>
@GeneratedValue</br>
</span><span style="color: #0000ff">private</span> Integer user_id;<span style="color: #008000">//</span><span style="color: #008000">用户序号</span></br>
@Column(unique=true)
private String name;//账户
private String password;//密码<span style="color: #0000ff">private</span> String salt;<span style="color: #008000">//</span><span style="color: #008000">盐</span></br></br> <span style="color: #0000ff">private</span> Integer state;<span style="color: #008000">//</span><span style="color: #008000">用户状态</span></br></br> <span style="color: #0000ff">private</span> String createtime;<span style="color: #008000">//</span><span style="color: #008000">创建时间</span></br></br>
@ManyToMany(fetch=FetchType.EAGER)//立即从数据库中进行加载数据;
@JoinTable(name="User_Role",joinColumns={@JoinColumn(name="user_id")},
inverseJoinColumns={@JoinColumn(name="role_id")})
private List<Role> roleList;@JsonBackReference
</span><span style="color: #0000ff">public</span> List<Role><span style="color: #000000"> getRoleList(){</br>
</span><span style="color: #0000ff">return</span><span style="color: #000000"> roleList;</br>
}</br>
</br>
</span><span style="color: #0000ff">public</span> <span style="color: #0000ff">void</span> setRoleList(List<Role><span style="color: #000000"> roleList){</br>
</span><span style="color: #0000ff">this</span>.roleList=<span style="color: #000000">roleList;</br>
}</br>
注:其它getter和setter省略</span><span style="color: #000000">
}

关于为什么要在getRolelist这个方法上加上@JsonBackReference注解,可以查看这篇文章http://blog.csdn.net/maxu12345/article/details/45538157
Role实体(角色):

package com.cy.coo.bean; import java.io.Serializable;
import java.util.ArrayList;
import java.util.List; import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany; import com.fasterxml.jackson.annotation.JsonBackReference; @Entity
public class Role implements Serializable {
private static final long serialVersionUID = 1L;@Id</br>
@GeneratedValue</br>
</span><span style="color: #0000ff">private</span> Integer role_id;<span style="color: #008000">//</span><span style="color: #008000">角色序号</span></br></br> <span style="color: #0000ff">private</span> String role_name;<span style="color: #008000">//</span><span style="color: #008000">角色名称</span></br></br> <span style="color: #0000ff">private</span> String role_description;<span style="color: #008000">//</span><span style="color: #008000">角色描述</span></br></br>
@ManyToMany
@JoinTable(name = "User_Role", joinColumns = { @JoinColumn(name = "role_id") }, inverseJoinColumns = {
@JoinColumn(name = "user_id") })
private List<User> userList=new ArrayList<>();@ManyToMany<span style="color: #ff0000">(fetch</span></span><span style="color: #ff0000">=</span><span style="color: #000000"><span style="color: #ff0000">FetchType.EAGER)</span></br>
@JoinTable(name</span>="Role_Function",joinColumns={@JoinColumn(name="role_id")},inverseJoinColumns=<span style="color: #000000">{</br>
@JoinColumn(name</span>="function_id"<span style="color: #000000">)})</br>
</span><span style="color: #0000ff">private</span> List<Function> functionList=<span style="color: #0000ff">new</span> ArrayList<><span style="color: #000000">();</br></br> @JsonBackReference</br>
</span><span style="color: #0000ff">public</span> List<Function><span style="color: #000000"> getFunctionList(){</br>
</span><span style="color: #0000ff">return</span><span style="color: #000000"> functionList;</br>
}</br>
</br>
</span><span style="color: #0000ff">public</span> <span style="color: #0000ff">void</span> setFunctionList(List<Function><span style="color: #000000"> functionList){</br>
</span><span style="color: #0000ff">this</span>.functionList=<span style="color: #000000">functionList;</br>
}</br> @JsonBackReference</br>
</span><span style="color: #0000ff">public</span> List<User><span style="color: #000000"> getUserList() {</br>
</span><span style="color: #0000ff">return</span><span style="color: #000000"> userList;</br>
}</br></br> </span><span style="color: #0000ff">public</span> <span style="color: #0000ff">void</span> setUserList(List<User><span style="color: #000000"> userList) {</br>
</span><span style="color: #0000ff">this</span>.userList =<span style="color: #000000"> userList;</br>
}</br></br> </span><span style="color: #0000ff">public</span><span style="color: #000000"> Integer getRole_id() {</br>
</span><span style="color: #0000ff">return</span><span style="color: #000000"> role_id;</br>
}</br></br> </span><span style="color: #0000ff">public</span> <span style="color: #0000ff">void</span><span style="color: #000000"> setRole_id(Integer role_id) {</br>
</span><span style="color: #0000ff">this</span>.role_id =<span style="color: #000000"> role_id;</br>
}</br></br></br> </span><span style="color: #0000ff">public</span><span style="color: #000000"> String getRole_name() {</br>
</span><span style="color: #0000ff">return</span><span style="color: #000000"> role_name;</br>
}</br></br> </span><span style="color: #0000ff">public</span> <span style="color: #0000ff">void</span><span style="color: #000000"> setRole_name(String role_name) {</br>
</span><span style="color: #0000ff">this</span>.role_name =<span style="color: #000000"> role_name;</br>
}</br> </span><span style="color: #0000ff">public</span><span style="color: #000000"> String getRole_description() {</br>
</span><span style="color: #0000ff">return</span><span style="color: #000000"> role_description;</br>
}</br> </span><span style="color: #0000ff">public</span> <span style="color: #0000ff">void</span><span style="color: #000000"> setRole_description(String role_description) {</br>
</span><span style="color: #0000ff">this</span>.role_description =<span style="color: #000000"> role_description;</br>
}</br>
}

Function实体(权限):

package com.cy.coo.bean; import java.util.List; import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany; @Entity
public class Function {
@Id
@GeneratedValue
private Integer function_id;//功能序号<span style="color: #0000ff">private</span> String permission;<span style="color: #008000">//</span><span style="color: #008000">权限字符串</span></br>
@ManyToMany</br>
@JoinTable(name </span>= "Role_Function", joinColumns = { @JoinColumn(name = "function_id") }, inverseJoinColumns =<span style="color: #000000"> {</br>
@JoinColumn(name </span>= "role_id"<span style="color: #000000">) })</br>
</span><span style="color: #0000ff">private</span> List<Role><span style="color: #000000"> roleList;</br></br> </span><span style="color: #0000ff">public</span> List<Role><span style="color: #000000"> getRoleList() {</br>
</span><span style="color: #0000ff">return</span><span style="color: #000000"> roleList;</br>
}</br> </span><span style="color: #0000ff">public</span> <span style="color: #0000ff">void</span> setRoleList(List<Role><span style="color: #000000"> roleList) {</br>
</span><span style="color: #0000ff">this</span>.roleList =<span style="color: #000000"> roleList;</br>
}</br> </span><span style="color: #0000ff">public</span><span style="color: #000000"> Integer getFunction_id() {</br>
</span><span style="color: #0000ff">return</span><span style="color: #000000"> function_id;</br>
}</br> </span><span style="color: #0000ff">public</span> <span style="color: #0000ff">void</span><span style="color: #000000"> setFunction_id(Integer function_id) {</br>
</span><span style="color: #0000ff">this</span>.function_id =<span style="color: #000000"> function_id;</br>
}</br></br></br> </span><span style="color: #0000ff">public</span><span style="color: #000000"> String getPermission() {</br>
</span><span style="color: #0000ff">return</span><span style="color: #000000"> permission;</br>
}</br></br> </span><span style="color: #0000ff">public</span> <span style="color: #0000ff">void</span><span style="color: #000000"> setPermission(String permission) {</br>
</span><span style="color: #0000ff">this</span>.permission =<span style="color: #000000"> permission;</br>
}</br>
}

这几个实体类的具体关系如下图,也完美的解释了为什么会生成5张表:
三、写一个与前端交互的controller方法,service层的具体逻辑的方法
@PostMapping(value = "/logon")
public Object logon(@RequestBody Login user) {</span><span style="color: #0000ff">return</span><span style="color: #000000"> userService.login(user);</br>
}</span></pre>
这个方法就是将前端传来的username和password封装到Login类中,Login类也只有这两个属性,然后调用Service层的login方法来处理。下面是service的login方法:

/**
* 用户登录 create by yyc 2017年5月12日下午4:31:26
*/
@Override
public Object login(Login user) {
String username = user.getUsername().trim();
String password = user.getPassword().trim();</span><span style="color: #008000">//</span><span style="color: #008000"> 检查空值</span></br>
<span style="color: #0000ff">if</span> (!<span style="color: #000000">CheckObjectField.CheckField(user)) {</br>
</span><span style="color: #0000ff">throw</span> <span style="color: #0000ff">new</span> ResultException(CheckObjectField.FieldName + "为空!"<span style="color: #000000">);
}</br></br></br> </span><span style="color: #008000">//</span><span style="color: #008000"> 检查用户状态</span></br>
Integer userState =<span style="color: #000000"> userRepository.findUserState(username);</br>
</span><span style="color: #0000ff">if</span> (<span style="color: #0000ff">new</span> Integer("1"<span style="color: #000000">).equals(userState)) {</br>
</span><span style="color: #0000ff">throw</span> <span style="color: #0000ff">new</span> ResultException("该用户已锁定"<span style="color: #000000">);</br>
}</br></br> </span><span style="color: #008000">//</span><span style="color: #008000"> 1、获取Subject实例对象</span></br>
Subject currentUser =<span style="color: #000000"> SecurityUtils.getSubject();</br></br> </span><span style="color: #008000">//</span><span style="color: #008000"> 2、判断当前用户是否登录</span></br>
<span style="color: #0000ff">if</span> (currentUser.isAuthenticated() == <span style="color: #0000ff">false</span><span style="color: #000000">) {</br>
</span><span style="color: #008000">//</span><span style="color: #008000"> 3、将用户名和密码封装到UsernamePasswordToken</span></br>
UsernamePasswordToken token = <span style="color: #0000ff">new</span><span style="color: #000000"> UsernamePasswordToken(username, password);</br></br> </span><span style="color: #008000">//</span><span style="color: #008000"> 4、认证</span></br>
<span style="color: #0000ff">try</span><span style="color: #000000"> {</br>
currentUser.login(token);</span><span style="color: #008000">//</span><span style="color: #008000"> 传到MyAuthorizingRealm类中的方法进行认证</span>
Session session =<span style="color: #000000"> currentUser.getSession();</br>
session.setAttribute(</span>"username"<span style="color: #000000">, username);</br>
} </span><span style="color: #0000ff">catch</span><span style="color: #000000"> (AuthenticationException e) {</br>
</span><span style="color: #0000ff">throw</span> <span style="color: #0000ff">new</span> ResultException("密码或用户名错误"<span style="color: #000000">);</br>
}</br>
}</br>
</span><span style="color: #008000">//</span><span style="color: #008000"> 根据用户名查询角色信息</span></br>
List<String> RoleNames =<span style="color: #000000"> roleService.findRoleName(username);</br></br> </span><span style="color: #0000ff">return</span> <span style="color: #0000ff">new</span><span style="color: #000000"> LoginReturn(username, RoleNames);</br> }</span></pre>
service中主要是将用户名和密码封装到shiro的UsernamePasswordToken中,然后将token对象放到SecurityUtils.getSubject()的login方法中,以便shiro认证登录使用。认证失败就会抛出AuthenticationException这个异常,就对异常进行相应的操作,这里的处理是抛出一个自定义异常ResultException。
四、写我认为的shiro的核心类

package com.cy.coo.shiro; import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UsernamePasswordToken;
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.util.ByteSource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired; import com.cy.coo.bean.Function;
import com.cy.coo.bean.Role;
import com.cy.coo.bean.User;
import com.cy.coo.service.UserService; /**
*
*
- @author E-mail:34782655@qq.com
- @version 创建时间:2017年5月8日 上午10:50:50
- 类说明:
- --
*/
public class MyAuthorizingRealm extends AuthorizingRealm {
</span><span style="color: #0000ff">private</span> <span style="color: #0000ff">final</span> <span style="color: #0000ff">static</span> Logger logger=LoggerFactory.getLogger(MyAuthorizingRealm.<span style="color: #0000ff">class</span><span style="color: #000000">);
@Autowired
</span><span style="color: #0000ff">private</span><span style="color: #000000"> UserService userService;</br>
</span><span style="color: #008000">//</span><span style="color: #008000">shiro的权限配置方法</span></br>
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
logger.info(</span>"权限配置-->doGetAuthorizationInfo"<span style="color: #000000">);</br></br>
SimpleAuthorizationInfo authorizationInfo </span>= <span style="color: #0000ff">new</span><span style="color: #000000"> SimpleAuthorizationInfo();</br>
logger.info(</span>"----------------------------->"+<span style="color: #000000">principals.getPrimaryPrincipal());</br>
User user</span>=<span style="color: #000000">(User) principals.getPrimaryPrincipal();</br>
</span><span style="color: #0000ff">for</span><span style="color: #000000">(Role role:user.getRoleList()){</br>
authorizationInfo.addRole(role.getRole_name());</br>
</span><span style="color: #0000ff">for</span><span style="color: #000000">(Function function:role.getFunctionList()){</br>
authorizationInfo.addStringPermission(function.getPermission());</br>
}</br>
}</br>
logger.info(</span>"用户"+user.getName()+"具有的角色:"+<span style="color: #000000">authorizationInfo.getRoles());</br>
logger.info(</span>"用户"+user.getName()+"具有的权限:"+<span style="color: #000000">authorizationInfo.getStringPermissions());</br></br>
</span><span style="color: #0000ff">return</span><span style="color: #000000"> authorizationInfo;</br>
}
</span><span style="color: #008000">//</span><span style="color: #008000">shiro的身份验证方法</span></br>
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
logger.info(</span>"正在验证身份..."<span style="color: #000000">);</br>
SimpleAuthenticationInfo info</span>=<span style="color: #0000ff">null</span><span style="color: #000000">;</br></br>
</span><span style="color: #008000">//</span><span style="color: #008000">将token转换成UsernamePasswordToken</span></br>
UsernamePasswordToken upToken =<span style="color: #000000"> (UsernamePasswordToken) token;</br>
</span><span style="color: #008000">//</span><span style="color: #008000">从转换后的token中获取用户名</span></br>
String username=<span style="color: #000000"> upToken.getUsername(); </br>
logger.info(</span>"----->"+<span style="color: #000000">username);</br></br>
</span><span style="color: #008000">//</span><span style="color: #008000">查询数据库,得到用户</span></br>
User user=<span style="color: #000000">userService.findByName(username);</br>
</span><span style="color: #0000ff">if</span>(user==<span style="color: #0000ff">null</span><span style="color: #000000">){</br>
</span><span style="color: #0000ff">return</span> <span style="color: #0000ff">null</span><span style="color: #000000">;</br>
}</br>
</span><span style="color: #008000">//</span><span style="color: #008000">得到加密密码的盐值</span></br>
ByteSource salt =<span style="color: #000000"> ByteSource.Util.bytes(user.getSalt());</br>
// logger.info("加密密码的盐:"+salt);
// //得到盐值加密后的密码:只用于方便数据库测试,后期不会用到。
// Object md = new SimpleHash("MD5",upToken.getPassword(),salt,1024);
// logger.info("盐值加密后的密码:"+md);
info = new SimpleAuthenticationInfo(
user, //用户名
user.getPassword(), //密码
salt, //加密的盐值
getName() //realm name
);
return info;
}
}

这个类继承shiro的AuthorizingRealm ,主要有两个方法,一个是权限配置,一个是身份认证,权限配置:当我们要用到权限时shiro会回调doGetAuthorizationInfo这个方法,对当前的用户分配权限,这个方法中的嵌套for循环是怎么回事呢,其实就是将数据库中的对应角色、权限放进shiro中,让他来管理,这需要实体类User中有getRoleList()、getRole_name()和getFunctionList()、getPermission这几个方法,这几个个方法就是设计数据库和实体类时的东西了,关于shiro权限相关的实体类在前面已经给出了。身份认证:在用户登录认证的时候回调,认证失败就抛出AuthenticationException。
五、shiro配置类

package com.cy.coo.shiro; import java.util.LinkedHashMap;
import java.util.Map; import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.cache.ehcache.EhCacheManager;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.CookieRememberMeManager;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.servlet.SimpleCookie;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.cache.ehcache.EhCacheManagerFactoryBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource; @Configuration // 等价于beans
public class ShiroConfig {</span><span style="color: #0000ff">private</span> <span style="color: #0000ff">static</span> <span style="color: #0000ff">final</span> Logger log = LoggerFactory.getLogger(ShiroFilterFactoryBean.<span style="color: #0000ff">class</span><span style="color: #000000">);</br></br> @Bean(name </span>= "securityManager"<span style="color: #000000">)</br>
</span><span style="color: #0000ff">public</span> SecurityManager securityManager(@Qualifier("authRealm"<span style="color: #000000">) MyAuthorizingRealm authRealm,</br>
@Qualifier(</span>"cookieRememberMeManager"<span style="color: #000000">) CookieRememberMeManager cookieRememberMeManager) {</br>
log.info(</span>"securityManager()"<span style="color: #000000">);</br>
DefaultWebSecurityManager securityManager </span>= <span style="color: #0000ff">new</span><span style="color: #000000"> DefaultWebSecurityManager();</br>
</span><span style="color: #008000">//</span><span style="color: #008000"> 设置realm.</span></br>
securityManager.setRealm(authRealm);
</span><span style="color: #008000">//</span><span style="color: #008000"> 设置rememberMe管理器</span></br>
securityManager.setRememberMeManager(cookieRememberMeManager);
</span><span style="color: #0000ff">return</span><span style="color: #000000"> securityManager;</br>
} </span><span style="color: #008000">/**</span><span style="color: #008000"></br>
* realm</br>
*
* </span><span style="color: #808080">@return</span></br>
<span style="color: #008000">*/</span><span style="color: #000000"></br>
@Bean(name </span>= "authRealm"<span style="color: #000000">)</br>
</span><span style="color: #0000ff">public</span><span style="color: #000000"> MyAuthorizingRealm myAuthRealm(</br>
@Qualifier(</span>"hashedCredentialsMatcher"<span style="color: #000000">) HashedCredentialsMatcher matcher,</br>
@Qualifier(</span>"ehCacheManager"<span style="color: #000000">) EhCacheManager ehCacheManager) {</br>
log.info(</span>"myShiroRealm()"<span style="color: #000000">);</br>
MyAuthorizingRealm myAuthorizingRealm </span>= <span style="color: #0000ff">new</span><span style="color: #000000"> MyAuthorizingRealm();</br>
</span><span style="color: #008000">//</span><span style="color: #008000"> 设置密码凭证匹配器</span></br>
myAuthorizingRealm.setCredentialsMatcher(matcher); <span style="color: #008000">//</span><span style="color: #008000"> myShiroRealm.setCredentialsMatcher(hashedCredentialsMatcher());</br>
</span><span style="color: #008000">//</span><span style="color: #008000"> 设置缓存管理器</span></br>
myAuthorizingRealm.setCacheManager(ehCacheManager);
</span><span style="color: #0000ff">return</span><span style="color: #000000"> myAuthorizingRealm;</br>
}</br>
/**
* 缓存管理器
* @return
*/
@Bean(value="ehCacheManager")
public EhCacheManager ehCacheManager(@Qualifier("ehCacheManagerFactoryBean") EhCacheManagerFactoryBean bean) {
log.info("ehCacheManager()");
EhCacheManager cacheManager = new EhCacheManager();
cacheManager.setCacheManagerConfigFile("classpath:ehcache-shiro.xml");
return cacheManager;
}</span><span style="color: #008000">/**</span><span style="color: #008000"></br>
* cookie对象;</br>
* </br>
* </span><span style="color: #808080">@return</span></br>
<span style="color: #008000">*/</span><span style="color: #000000"></br>
@Bean</br>
</span><span style="color: #0000ff">public</span><span style="color: #000000"> SimpleCookie rememberMeCookie() {</br>
log.info(</span>"rememberMeCookie()"<span style="color: #000000">);</br>
</span><span style="color: #008000">//</span><span style="color: #008000"> 这个参数是cookie的名称,对应前端的checkbox 的name = rememberMe</span></br>
SimpleCookie simpleCookie = <span style="color: #0000ff">new</span> SimpleCookie("rememberMe"<span style="color: #000000">);</br>
</span><span style="color: #008000">//</span><span style="color: #008000"> <!-- 记住我cookie生效时间30天(259200) ,单位秒;--></span></br>
simpleCookie.setMaxAge(259200<span style="color: #000000">);</br>
</span><span style="color: #0000ff">return</span><span style="color: #000000"> simpleCookie;</br>
}</br> </span><span style="color: #008000">/**</span><span style="color: #008000"></br>
* 记住我管理器 cookie管理对象;</br></br>
*
* </span><span style="color: #808080">@return</span></br>
<span style="color: #008000">*/</span><span style="color: #000000"></br>
@Bean(name </span>= "cookieRememberMeManager"<span style="color: #000000">)</br>
</span><span style="color: #0000ff">public</span><span style="color: #000000"> CookieRememberMeManager rememberMeManager() {</br>
System.out.println(</span>"rememberMeManager()"<span style="color: #000000">);</br>
CookieRememberMeManager cookieRememberMeManager </span>= <span style="color: #0000ff">new</span><span style="color: #000000"> CookieRememberMeManager();</br>
cookieRememberMeManager.setCookie(rememberMeCookie());</br>
</span><span style="color: #0000ff">return</span><span style="color: #000000"> cookieRememberMeManager;</br>
}</br> </span><span style="color: #008000">/**</span><span style="color: #008000">
* 密码匹配凭证管理器
*
* </span><span style="color: #808080">@return</span></br>
<span style="color: #008000">*/</span><span style="color: #000000"></br>
@Bean(name </span>= "hashedCredentialsMatcher"<span style="color: #000000">)</br>
</span><span style="color: #0000ff">public</span><span style="color: #000000"> HashedCredentialsMatcher hashedCredentialsMatcher() {</br>
log.info(</span>"hashedCredentialsMatcher()"<span style="color: #000000">);</br>
HashedCredentialsMatcher hashedCredentialsMatcher </span>= <span style="color: #0000ff">new</span><span style="color: #000000"> HashedCredentialsMatcher();</br></br> hashedCredentialsMatcher.setHashAlgorithmName(</span>"MD5");<span style="color: #008000">//</span><span style="color: #008000"> 散列算法:这里使用MD5算法;</span></br>
hashedCredentialsMatcher.setHashIterations(1024);<span style="color: #008000">//</span><span style="color: #008000"> 散列的次数,比如散列两次,相当于</br>
</span><span style="color: #008000">//</span><span style="color: #008000"> md5(md5(""));</span></br></br> <span style="color: #0000ff">return</span><span style="color: #000000"> hashedCredentialsMatcher;</br>
}</br> </span><span style="color: #008000">/**</span><span style="color: #008000"></br>
* 开启shiro aop注解支持. 使用代理方式;所以需要开启代码支持; Controller才能使用@RequiresPermissions</br></br>
*
* </span><span style="color: #808080">@param</span><span style="color: #008000"> securityManager</br>
* </span><span style="color: #808080">@return</span></br>
<span style="color: #008000">*/</span><span style="color: #000000"></br>
@Bean</br>
</span><span style="color: #0000ff">public</span><span style="color: #000000"> AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(</br>
@Qualifier(</span>"securityManager"<span style="color: #000000">) SecurityManager securityManager) {</br>
log.info(</span>"authorizationAttributeSourceAdvisor()"<span style="color: #000000">);</br>
AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor </span>= <span style="color: #0000ff">new</span><span style="color: #000000"> AuthorizationAttributeSourceAdvisor();</br>
authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);</br>
</span><span style="color: #0000ff">return</span><span style="color: #000000"> authorizationAttributeSourceAdvisor;</br>
}</br> @Bean</br>
</span><span style="color: #0000ff">public</span> ShiroFilterFactoryBean shiroFilter(@Qualifier("securityManager"<span style="color: #000000">) SecurityManager securityManager) {</br>
log.info(</span>"shirFilter()"<span style="color: #000000">);</br>
ShiroFilterFactoryBean shiroFilterFactoryBean </span>= <span style="color: #0000ff">new</span><span style="color: #000000"> ShiroFilterFactoryBean();</br></br> </span><span style="color: #008000">//</span><span style="color: #008000"> 必须设置 SecurityManager</span></br>
shiroFilterFactoryBean.setSecurityManager(securityManager);
</span><span style="color: #008000">//</span><span style="color: #008000"> 拦截器.</span></br>
Map<String, String> map = <span style="color: #0000ff">new</span> LinkedHashMap<String, String><span style="color: #000000">();</br></br> map.put(</span>"/logout", "logout"<span style="color: #000000">);</br>
map.put(</span>"/login", "anon"<span style="color: #000000">);</br>
map.put(</span>"/logon", "anon"<span style="color: #000000">);</br></br> map.put(</span>"/**", "authc"<span style="color: #000000">);</br></br> </span><span style="color: #008000">//</span><span style="color: #008000"> 如果不设置默认会自动寻找Web工程根目录下的"/login.jsp"页面</span></br>
shiroFilterFactoryBean.setLoginUrl("/login"<span style="color: #000000">);</br>
</span><span style="color: #008000">//</span><span style="color: #008000"> 登录成功后要跳转的链接</span></br>
shiroFilterFactoryBean.setSuccessUrl("/index"<span style="color: #000000">);</br>
</span><span style="color: #008000">//</span><span style="color: #008000"> 未授权界面;</span></br>
shiroFilterFactoryBean.setUnauthorizedUrl("/unauthorized"<span style="color: #000000">);</br></br> shiroFilterFactoryBean.setFilterChainDefinitionMap(map);</br>
</span><span style="color: #0000ff">return</span><span style="color: #000000"> shiroFilterFactoryBean;</br>
}</br>
}

这个没什么好说的,最后一个类是shiro的过滤器配置。可以看到我在每个方法上面加了一个@Bean(name="..."),其实这是spring的注解,将这个类放到spring容器中管理,在方法形参中使用@Qualifier(...)来使用它,以致于我们在方法体中调用某个方法时就方面多了。
在这里,关于shiro在springboot中的基础配置就完成了。下面是期间遇到的错误解决方案:

@Configuration
public class HibernateConfig {
@Bean
public FilterRegistrationBean registerOpenEntityManagerInViewFilterBean() {
FilterRegistrationBean registrationBean = new FilterRegistrationBean();
OpenEntityManagerInViewFilter filter = new OpenEntityManagerInViewFilter();
registrationBean.setFilter(filter);
registrationBean.setOrder(5);
return registrationBean;
}
}

参考文章:
http://www.jianshu.com/p/a827ecdda99f
http://www.w_2bc.com/article/201653 /*这个链接博客园不让我发啊,把w_2_b_c中的下划线删了即可*/
错误二:这个在前面也提到过了,返回json数据出现Could not write JSON document: Infinite recursion(无法编写JSON文档:无限递归 );
在后面的使用中发现这个错误也是这样解决的,java.lang.IllegalStateException: Cannot call sendError() after the response has been committed,错误页面到最后就是这样,如图:
解决方法:
原文地址:https://www.cnblogs.com/hyyq/p/6886004.html
</div>
Springboot+shiro配置笔记+错误小结(转)的更多相关文章
- (转)Springboot+shiro配置笔记+错误小结
springboot不像springmvc,它没有xml配置文件,那该如何配置shiro呢,其实也不难,用java代码+注解来解决这个问题.仅以此篇记录我对shiro的学习,如有对过客造成不便,实在抱 ...
- Springboot+shiro配置笔记+错误小结
软件152 尹以操 springboot不像springmvc,它没有xml配置文件,那该如何配置shiro呢,其实也不难,用java代码+注解来解决这个问题.仅以此篇记录我对shiro的学习,如有对 ...
- springboot shiro配置
导入相关包(这里配合使用Ehcache缓存) <dependency> <groupId>org.apache.shiro</groupId> <artifa ...
- SpringBoot整合Shiro 二:Shiro配置类
环境搭建见上篇:SpringBoot整合Shiro 一:搭建环境 Shiro配置类配置 shiro的配置主要集中在 ShiroFilterFactoryBean 中 关于权限: anon:无需认证就可 ...
- springboot学习笔记:11.springboot+shiro+mysql+mybatis(通用mapper)+freemarker+ztree+layui实现通用的java后台管理系统(权限管理+用户管理+菜单管理)
一.前言 经过前10篇文章,我们已经可以快速搭建一个springboot的web项目: 今天,我们在上一节基础上继续集成shiro框架,实现一个可以通用的后台管理系统:包括用户管理,角色管理,菜单管理 ...
- SpringBoot+Shiro学习(七):Filter过滤器管理
SpringBoot+Shiro学习(七):Filter过滤器管理 Hiwayz 关注 0.5 2018.09.06 19:09* 字数 1070 阅读 5922评论 1喜欢 20 先从我们写的一个 ...
- Shiro学习笔记(5)——web集成
Web集成 shiro配置文件shiroini 界面 webxml最关键 Servlet 測试 基于 Basic 的拦截器身份验证 Web集成 大多数情况.web项目都会集成spring.shiro在 ...
- springboot+shiro
作者:纯洁的微笑 出处:http://www.ityouknow.com/ 这篇文章我们来学习如何使用Spring Boot集成Apache Shiro.安全应该是互联网公司的一道生命线,几乎任何的公 ...
- Spring Cloud之路:(七)SpringBoot+Shiro实现登录认证和权限管理
版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/sage_wang/article/details/79592269一.Shiro介绍1.Shiro是 ...
随机推荐
- 刘汝佳 算法竞赛-入门经典 第二部分 算法篇 第六章 2(Binary Trees)
112 - Tree Summing 题目大意:给出一个数,再给一颗树,每个头节点的子树被包含在头节点之后的括号里,寻找是否有从头节点到叶子的和与给出的数相等,如果有则输出yes,没有输出no! 解题 ...
- 03009_SQL注入问题
1.注入问题 (1)假设有登录案例SQL语句如下: SELECT * FROM 用户表 WHERE NAME = 用户输入的用户名 AND PASSWORD = 用户输的密码; (2)此时,当用户输入 ...
- 洛谷——P3384 【模板】树链剖分
https://www.luogu.org/problem/show?pid=3384#sub 题目描述 如题,已知一棵包含N个结点的树(连通且无环),每个节点上包含一个数值,需要支持以下操作: 操作 ...
- [React] Use the URL as the source of truth in React
In Single Page Apps we're used to fetch the data on event callbacks. That disables the capacity to u ...
- virmon防火墙64位正式版(暂定)公布
ChangeLog: 2015-06-2564位版本号签名问题临时得到解决.还要致谢一下某位黑客. 支持版本号x64 Windows Vista.7.8.8.1以上等.个人仅仅在Windows7上做了 ...
- *android抓包工具——fiddler抓包分析api接口
本文地址:http://blog.csdn.net/u011733020 首先,写这个仅仅是为了学习.不是要做什么违法的事情,假设有问题,有关部门 请联系我,立刻删除. 不要查我水表. 正题:这里介绍 ...
- linux host主机名配置
1.查看主机名 #hostname 2.查看ip #ifconfig 2.添加主机名配置 #vi /etc/hosts 新增一行 172.23.26.195 vhost145.idmp.safe
- worktools-不同分辨率下图片移植
1.下载需要移植的平台代码 1)查看手机需要的项目平台信息:adb shell getprop | gerp flavor ----->mt6732_m561_p2_kangjia_cc ...
- [NOI.AC#35]string 缩点+拓扑排序
链接 因为有交换相邻字母,因此给你字符串就相当于给你了这个字符串的所有排列 把等价的串映射到整数范围,再根据 \(m\) 种魔法连边,缩点后在 DAG 上DP即可 无耻地用了int128 #inclu ...
- AngularJsDEMO
接触AngularJs时间不长,纯粹是学着好玩而已,因此没有深挖原理,针对理论性的知识,园子里面有很多介绍,我就不多介绍了. 这里写了个简单的DEMO,部署起来就可以直接运行了,里面 大概用了最基础的 ...