springboot学习心得3
整合springboot shiro
目录结构
在引入web,mysql,mybatis 的项目基础上引入shiro,thymeleaf
增加yml文件(配置信息)
-
#默认使用配置
-
spring:
-
profiles:
-
active: dev
-
-
#公共配置与profiles选择无关
-
mybatis:
-
typeAliasesPackage: com.springboot.shiro.model
-
mapperLocations: classpath:mapper/*.xml
-
#sql 日志
-
logging:
-
level:
-
com.springboot.shiro.dao: trace
-
---
-
#开发配置
-
spring:
-
profiles: dev
-
datasource:
-
url: jdbc:mysql://localhost:3306/qidi_shiro
-
username: root
-
password: geyanxin
-
driver-class-name: com.mysql.jdbc.Driver
-
创建自定义MyShiroRealm
- package com.springboot.shiro.config;
import javax.annotation.Resource;
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.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import com.springboot.shiro.model.User;
import com.springboot.shiro.service.UserService;
public class MyShiroRealm extends AuthorizingRealm{
@Resource
private UserService userService;
/**
* 权限设置
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
String userName=(String)principals.getPrimaryPrincipal();
SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
authorizationInfo.setRoles(userService.getRoles(userName));
return authorizationInfo;
}
/**
* 身份认证
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
//获取用户的输入的账号.
String userName = (String)token.getPrincipal();
//通过username从数据库中查找 User对象,如果找到,没找到.
User user = userService.getByUserName(userName);
if(user == null){
return null;
}
SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(
user.getName(), //用户名
user.getUserPassword(), //密码
getName() //realm name
);
return authenticationInfo;
}
}
创建shiroConfig
- package com.springboot.shiro.config;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.spring.LifecycleBeanPostProcessor;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.handler.SimpleMappingExceptionResolver;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Properties;
@Configuration
public class ShiroConfig {
@Bean
public ShiroFilterFactoryBean shirFilter(SecurityManager securityManager) {
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
shiroFilterFactoryBean.setSecurityManager(securityManager);
//拦截器.
Map<String,String> filterChainDefinitionMap = new LinkedHashMap<String,String>();
// 配置不会被拦截的链接 顺序判断
filterChainDefinitionMap.put("/static/**", "anon");
//配置退出 过滤器,其中的具体的退出代码Shiro已经替我们实现了
filterChainDefinitionMap.put("/logout", "logout");
//<!-- 过滤链定义,从上向下顺序执行,一般将/**放在最为下边 -->:这是一个坑呢,一不小心代码就不好使了;
//<!-- authc:所有url都必须认证通过才可以访问; anon:所有url都都可以匿名访问-->
filterChainDefinitionMap.put("/**", "authc");
// 如果不设置默认会自动寻找Web工程根目录下的"/login.jsp"页面
shiroFilterFactoryBean.setLoginUrl("/login");
// 登录成功后要跳转的链接
shiroFilterFactoryBean.setSuccessUrl("/index");
//未授权界面;
shiroFilterFactoryBean.setUnauthorizedUrl("/403");
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
return shiroFilterFactoryBean;
}
/**
* 凭证匹配器
* (由于我们的密码校验交给Shiro的SimpleAuthenticationInfo进行处理了
* )
* @return
*/ @Bean
public HashedCredentialsMatcher hashedCredentialsMatcher(){
HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
hashedCredentialsMatcher.setHashAlgorithmName("md5");//散列算法:这里使用MD5算法;
hashedCredentialsMatcher.setHashIterations(1);//散列的次数,如果括号内写2 --散列两次,相当于 md5(md5(""));
return hashedCredentialsMatcher;
}
@Bean
public MyShiroRealm myShiroRealm(){
MyShiroRealm myShiroRealm = new MyShiroRealm();
myShiroRealm.setCredentialsMatcher(hashedCredentialsMatcher());
return myShiroRealm;
}
@Bean
public SecurityManager securityManager(){
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
securityManager.setRealm(myShiroRealm());
return securityManager;
}
/**
* 开启shiro aop注解支持.
* 使用代理方式;所以需要开启代码支持;
* @param securityManager
* @return
*/
@Bean
public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager){
AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
return authorizationAttributeSourceAdvisor;
}
@Bean(name="simpleMappingExceptionResolver")
public SimpleMappingExceptionResolver
createSimpleMappingExceptionResolver() {
SimpleMappingExceptionResolver r = new SimpleMappingExceptionResolver();
Properties mappings = new Properties();
mappings.setProperty("DatabaseException", "databaseError");//数据库异常处理
mappings.setProperty("UnauthorizedException","403");
r.setExceptionMappings(mappings); // None by default
r.setDefaultErrorView("error"); // No default
r.setExceptionAttribute("ex"); // Default is "exception"
//r.setWarnLogCategory("example.MvcLogger"); // No default
return r;
}
@Bean
public static LifecycleBeanPostProcessor getLifecycleBeanPostProcessor() {
return new LifecycleBeanPostProcessor();
}
@Bean
public static DefaultAdvisorAutoProxyCreator getDefaultAdvisorAutoProxyCreator(){
return new DefaultAdvisorAutoProxyCreator();
}
}
值得注意的是必须加入LifecycleBeanPostProcessor ,DefaultAdvisorAutoProxyCreator这两个bean不然后期做测试时使用@RequiresRoles()会报错。
创建User实体
-
package com.springboot.shiro.model;
-
public class User {
-
private Integer id;
-
private String name;
-
private String userName;
-
private String userPassword;
-
private String userEmail;
-
private String userPhone;
-
private String isDisable;
-
private String department;
-
public Integer getId() {
-
return id;
-
}
-
public void setId(Integer id) {
-
this.id = id;
-
}
-
public String getName() {
-
return name;
-
}
-
public void setName(String name) {
-
this.name = name;
-
}
-
public String getUserName() {
-
return userName;
-
}
-
public void setUserName(String userName) {
-
this.userName = userName;
-
}
-
-
public String getUserPassword() {
-
return userPassword;
-
}
-
public void setUserPassword(String userPassword) {
-
this.userPassword = userPassword;
-
}
-
public String getUserEmail() {
-
return userEmail;
-
}
-
public void setUserEmail(String userEmail) {
-
this.userEmail = userEmail;
-
}
-
public String getUserPhone() {
-
return userPhone;
-
}
-
public void setUserPhone(String userPhone) {
-
this.userPhone = userPhone;
-
}
-
public String getIsDisable() {
-
return isDisable;
-
}
-
public void setIsDisable(String isDisable) {
-
this.isDisable = isDisable;
-
}
-
public String getDepartment() {
-
return department;
-
}
-
public void setDepartment(String department) {
-
this.department = department;
-
}
-
}
创建HomeController
- package com.springboot.shiro.controller;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import javax.servlet.http.HttpServletRequest;
import java.util.Map;
@Controller
public class HomeController {
@RequestMapping("/index")
public String index(){
return"/index";
}
@RequestMapping("/login")
public String login(HttpServletRequest request, Map<String, Object> map) throws Exception{
// 登录失败从request中获取shiro处理的异常信息。
// shiroLoginFailure:就是shiro异常类的全类名.
String exception = (String) request.getAttribute("shiroLoginFailure");
System.out.println("exception=" + exception);
String msg = "";
if (exception != null) {
if (UnknownAccountException.class.getName().equals(exception)) {
msg = "账号不存在:";
} else if (IncorrectCredentialsException.class.getName().equals(exception)) {
msg = "密码不正确:";
} else if ("kaptchaValidateFailed".equals(exception)) {
msg = "验证码错误";
} else {
msg = "else >> "+exception;
System.out.println("else -- >" + exception);
}
}
map.put("msg", msg);
// 此方法不处理登录成功,由shiro进行处理
return "/login";
}
@RequestMapping("/403")
public String unauthorizedRole(){
System.out.println("------没有权限-------");
return "403";
}
}
创建UserController
- package com.springboot.shiro.controller;
import java.util.ArrayList;
import java.util.List;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authz.annotation.Logical;
import org.apache.shiro.authz.annotation.RequiresRoles;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.Subject;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
@RequestMapping("/user")
public class UserController {
@RequestMapping("/login")
@RequiresRoles(value="admin",logical = Logical.OR)
public String login(){
System.out.println("shiwo");
return "success";
}
@RequestMapping("/list")
public @ResponseBody List<String> list(){
Subject subject= SecurityUtils.getSubject();
Session session=subject.getSession();
List<String> roleList=new ArrayList<String>();
if(subject.hasRole("admin")){
roleList.add("admin");
}
return roleList;
}
}
创建UserService
-
package com.springboot.shiro.service;
-
-
import java.util.Set;
-
import com.springboot.shiro.model.User;
-
public interface UserService {
-
User getByUserName(String userName);
-
Set<String> getRoles(String userName);
-
}
创建UserServiceImpl
-
package com.springboot.shiro.service.impl;
-
import java.util.Set;
-
import org.springframework.beans.factory.annotation.Autowired;
-
import org.springframework.stereotype.Service;
-
import com.springboot.shiro.dao.UserDao;
-
import com.springboot.shiro.model.User;
-
import com.springboot.shiro.service.UserService;
-
-
-
public class UserServiceImpl implements UserService{
-
-
private UserDao userDao;
-
-
public User getByUserName(String userName) {
-
return userDao.getByUserName(userName);
-
}
-
-
public Set<String> getRoles(String userName) {
-
return userDao.getRoles(userName);
-
}
-
}
创建UserDao
-
package com.springboot.shiro.dao;
-
import java.util.Set;
-
import org.apache.ibatis.annotations.Mapper;
-
import com.springboot.shiro.model.User;
-
-
-
public interface UserDao {
-
User getByUserName(String userName);
-
Set<String> getRoles(String userName);
-
}
创建UserDao.xml
-
<?xml version="1.0" encoding="UTF-8"?>
-
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
-
<mapper namespace="com.springboot.shiro.dao.UserDao">
-
<!-- 可根据自己的需求,是否要使用 -->
-
<resultMap type="com.springboot.shiro.model.User" id="userMap">
-
<result property="id" column="id"/>
-
<result property="name" column="name"/>
-
<result property="userName" column="user_name"/>
-
<result property="userPassword" column="user_password"/>
-
<result property="userEmail" column="user_email"/>
-
<result property="userPhone" column="user_phone"/>
-
<result property="isDisable" column="isDisable"/>
-
<result property="department" column="department"/>
-
</resultMap>
-
<select id="getByUserName" parameterType="String" resultMap="userMap">
-
select * from user where name = #{userName}
-
</select>
-
<select id="getRoles" parameterType="String" resultType="String">
-
SELECT `group`.group_name FROM `group`,user,group_user WHERE group_user.group_id=`group`.id
-
and group_user.user_id = `user`.id and `user`.`name`=#{userName}
-
</select>
-
</mapper>
创建index.html
-
-
<script src="https://cdn.bootcss.com/jquery/1.12.4/jquery.min.js"></script>
-
<html>
-
<head>
-
<meta charset="UTF-8">
-
<title>Insert title here</title>
-
</head>
-
<body>
-
<button type="button"οnclick="text()">查询</button>
-
<button type="button"οnclick="update()"class="admin">修改</button>
-
<button type="button"οnclick="del()"class="admin">删除</button>
-
</body>
-
<style>
-
.admin{
-
display: none
-
}
-
</style>
-
<script type="text/javascript">
-
$(function(){
-
console.log("asd")
-
$.ajax({
-
type: "POST",
-
url: "/user/list"
-
contentType: "application/json",
-
success: function(r){
-
console.log(r)
-
for(var i=0;i<r.length;i++){
-
console.log(r[i])
-
if(r[i]=="admin"){
-
console.log("admin用户")
-
$(".admin").css("display","block");
-
}
-
}
-
}
-
});
-
})
-
</script>
-
</html>
创建错误页面403.html
-
-
<html>
-
<head>
-
<meta charset="UTF-8">
-
<title>Insert title here</title>
-
</head>
-
<body>
-
权限不足
-
</body>
-
</html>
创建登录页面login.html
-
-
<html>
-
<head>
-
<meta charset="UTF-8">
-
<title>Insert title here</title>
-
</head>
-
<body>
-
错误信息:<h4 th:text="${msg}"></h4>
-
<form action="" method="post">
-
userName:<input type="text" name="username" value="admin"/><br/>
-
password:<input type="password" name="password" value="123456"><br/>
-
<input type="submit" value="login"/>
-
</form>
-
</body>
-
</html>
这里只做个简单的角色控制 没有涉及到权限控制 如果需要权限控制可以在自定义realm中添加如
- authorizationInfo.setStringPermissions(userService.getPermissions(userName));
启动项目 输入localhost:8080
如果用户名或者密码错误shiro会自动拦截
如果是admin用户
如果是普通用户
简单的角色验证
如果是普通用户登录在地址栏输入http://localhost:8080/user/login 会自动跳转权限不足403 页面所以不必担心被人知道路径从而访问数据

浙公网安备 33010602011771号