SpringBoot 통합 Shiro (초 상세 - 인증, 동적 권한 부여, remembeMe)
24175 단어 shiro 권한SpringBoot
이 프로젝트 는 SpringBoot 를 통 해 shiro 프레임 워 크 를 통합 하여 MybatisPlus 코드 생 성 기 를 사용 하여 간단 한 코드 를 만 들 었 습 니 다. 프로젝트 는 shiro 동적 권한 수여 와 인증, remembeMe 기억 기능 을 포함 합 니 다.
프로젝트 준비
(1) 가 져 오기 의존
4.0.0
org.springframework.boot
spring-boot-starter-parent
2.1.6.RELEASE
com.example
springboot-shiro
0.0.1-SNAPSHOT
springboot-shiro
Demo project for Spring Boot Shiro
1.8
org.springframework.boot
spring-boot-starter-thymeleaf
org.springframework.boot
spring-boot-starter-web
org.springframework.boot
spring-boot-starter-test
test
mysql
mysql-connector-java
5.1.46
com.baomidou
mybatis-plus-boot-starter
3.1.0
com.baomidou
mybatis-plus-generator
3.1.0
org.apache.velocity
velocity-engine-core
2.1
junit
junit
4.12
org.apache.shiro
shiro-spring
1.4.0
org.springframework.boot
spring-boot-devtools
true
net.sf.ehcache
ehcache-core
2.4.8
org.apache.shiro
shiro-ehcache
1.4.0
com.alibaba
fastjson
1.2.13
org.springframework
spring-context-support
5.1.8.RELEASE
org.springframework.boot
spring-boot-maven-plugin
true
(2) SpringBoot 프로필 설정
server.port=80
spring.mvc.static-path-pattern=/static/**
spring.resources.static-locations=classpath:/static/
#mysql
spring.datasource.url=jdbc:mysql://localhost:3306/crm?useUnicode=true&characterEncoding=utf-8
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
#mybatis-plus
mybatis-plus.type-aliases-package=com.example.leilei.entity
#
#
spring.devtools.restart.enabled=true
# ,
spring.freemarker.cache=false
(3) SpringBoot 시작 클래스 설정
@SpringBootApplication
@MapperScan(basePackages = "com.example.leilei.mapper")
public class SpringbootShiroApplication {
public static void main(String[] args) {
SpringApplication.run(SpringbootShiroApplication.class, args);
}
}
(4) Mybatis - plus 의 코드 생 성기 사용
도 구 를 합 리 적 으로 사용 하면 개발 시간 을 줄 일 수 있다.
public class CodeGenerator {
public static void main(String[] args) throws InterruptedException {
// Mybatis-Plus.properties
ResourceBundle rb = ResourceBundle.getBundle("springboot-shiro");
AutoGenerator mpg = new AutoGenerator();
//
GlobalConfig gc = new GlobalConfig();
gc.setOutputDir(rb.getString("OutputDir"));
gc.setFileOverride(true);
gc.setActiveRecord(true);// activeRecord
gc.setEnableCache(false);// XML
gc.setBaseResultMap(true);// XML ResultMap
gc.setBaseColumnList(false);// XML columList
gc.setAuthor(rb.getString("author"));
mpg.setGlobalConfig(gc);
//
DataSourceConfig dsc = new DataSourceConfig();
dsc.setDbType(DbType.MYSQL);
dsc.setTypeConvert(new MySqlTypeConvert());
dsc.setDriverName("com.mysql.jdbc.Driver");
dsc.setUsername(rb.getString("jdbc.user"));
dsc.setPassword(rb.getString("jdbc.pwd"));
dsc.setUrl(rb.getString("jdbc.url"));
mpg.setDataSource(dsc);
//
StrategyConfig strategy = new StrategyConfig();
// strategy.setTablePrefix(new String[] { "t_" });//
strategy.setNaming(NamingStrategy.underline_to_camel);//
strategy.setInclude(new String[]{"real_eseate"}); //
mpg.setStrategy(strategy);
//
PackageConfig pc = new PackageConfig();
pc.setParent(rb.getString("parent"));
pc.setController("controller");
pc.setService("service");
pc.setServiceImpl("service.impl");
pc.setEntity("domain");
pc.setMapper("mapper");
mpg.setPackageInfo(pc);
// , VM cfg.abc 【 】
InjectionConfig cfg = new InjectionConfig() {
@Override
public void initMap() {
}
};
List focList = new ArrayList();
// xml
focList.add(new FileOutConfig("/templates/mapper.xml.vm") {
@Override
public String outputFile(TableInfo tableInfo) {
return rb.getString("OutputDirXml")+ "/cn/leilei/mapper/" + tableInfo.getEntityName() + "Mapper.xml";
}
});
// query
/* focList.add(new FileOutConfig("/templates/query.java.vm") {
@Override
public String outputFile(TableInfo tableInfo) {
return rb.getString("OutputDomainDir")+ "/cn/leilei/query/" + tableInfo.getEntityName() + "Query.java";
}
});*/
// domain
focList.add(new FileOutConfig("/templates/entity.java.vm") {
@Override
public String outputFile(TableInfo tableInfo) {
return rb.getString("OutputDomainDir")+ "/cn/leilei/domain/" + tableInfo.getEntityName() + ".java";
}
});
cfg.setFileOutConfigList(focList);
mpg.setCfg(cfg);
// , copy mybatis-plus/src/main/resources/templates ,
// src/main/resources/templates , ,
TemplateConfig tc = new TemplateConfig();
//tc.setController("/templates/controller.java.vm");
// OR Null 。
tc.setEntity(null);
tc.setXml(null);
mpg.setTemplate(tc);
//
mpg.execute();
}
}
springboot-shiro.perproties
#
OutputDir=E://EEworkspac//springbootshiro//springboot-shiro//src//main//java
#query domain
OutputDomainDir=E://EEworkspac//springbootshiro//springboot-shiro//src//main//java
#
author=lei
#
jdbc.user=root
jdbc.pwd=root
jdbc.url=jdbc:mysql:///crm?useUnicode=true&characterEncoding=utf8
#
parent=cn.leilei
#xml resources
OutputDirXml=E://EEworkspac//springbootshiro//springboot-shiro//src//main//resources
2. 백 엔 드 코드 작성
(1) shiro 의 생명주기 설정
이 shiro 라 이 프 사이클 의 Bean 을 따로 설정 해 주세요.
/**
* shiro Bean
*/
@Configuration
public class ShiroLifecycleBeanPostProcessorConfig {
/**
* Shiro
*
* @return
*/
@Bean(name = "lifecycleBeanPostProcessor")
public LifecycleBeanPostProcessor getLifecycleBeanPostProcessor() {
return new LifecycleBeanPostProcessor();
}
}
(2) Realm 작성 인증, 권한 부여
public class MyRealm extends AuthorizingRealm {
@Autowired
private IEmployeeService employeeService;
@Autowired
private IPermissionService permissionService;
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
Employee employee = (Employee) principalCollection.getPrimaryPrincipal();
Long empId = employee.getId();
// id
List permissions = permissionService.getByEmpId(empId);
// shiro
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
for (Permission permission : permissions) {
info.addStringPermission(permission.getSn());
}
return info;
}
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;
String username = token.getUsername();
//
QueryWrapper wrapper = new QueryWrapper<>();
wrapper.eq("username",username);
Employee employee = employeeService.getOne(wrapper);
if(employee==null){
throw new UnknownAccountException(username);
}
// info
return new SimpleAuthenticationInfo(employee,employee.getPassword(), ByteSource.Util.bytes(MD5Utils.SALT),getName());
}
}
권한 수여 방법 은 링크 조회 가 필요 합 니 다.
elmplyee 에서 permission 표 조회
간단하게 썼 지만 실제 개발 에 서 는 sql 문 구 를 사용 하지 마 세 요 *
(3) shiro 의 설정 클래스
현재 프로젝트 에는 인증, 권한 수여, remembeMe 가 포함 되 어 있 습 니 다.
package com.example.leilei.config;
import com.example.leilei.entity.Permission;
import com.example.leilei.service.IEmployeeService;
import com.example.leilei.service.IPermissionService;
import com.example.leilei.shiro.realm.MyRealm;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.codec.Base64;
import org.apache.shiro.mgt.SecurityManager;
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.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
@Configuration
@AutoConfigureAfter(ShiroLifecycleBeanPostProcessorConfig.class)// Bean
public class ShiroConfig {
@Autowired
private IPermissionService permissionService;
/**
* SecurityManager Bean
* @return
*/
@Bean(name = "securityManager")
public SecurityManager securityManager(){
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
// Realm
securityManager.setRealm(myRealm());
//
securityManager.setRememberMeManager(rememberMeManager());
return securityManager;
}
/**
* -
* @return
*/
@Bean
public HashedCredentialsMatcher hashedCredentialsMatcher(){
HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
hashedCredentialsMatcher.setHashAlgorithmName("md5");//
hashedCredentialsMatcher.setHashIterations(10);//
return hashedCredentialsMatcher;
}
/**
* cookie ;
* rememberMeCookie() Cookie , cookie name,cookie 。
* @return
*/
@Bean
public SimpleCookie rememberMeCookie(){
//System.out.println("ShiroConfiguration.rememberMeCookie()");
// cookie , checkbox name = rememberMe
SimpleCookie simpleCookie = new SimpleCookie("rememberMe");
//
simpleCookie.setMaxAge(259200);
return simpleCookie;
}
/**
* cookie ;
* rememberMeManager() rememberMe , rememberMe securityManager
* @return
*/
@Bean
public CookieRememberMeManager rememberMeManager(){
//System.out.println("ShiroConfiguration.rememberMeManager()");
CookieRememberMeManager cookieRememberMeManager = new CookieRememberMeManager();
cookieRememberMeManager.setCookie(rememberMeCookie());
//rememberMe cookie AES (128 256 512 )
cookieRememberMeManager.setCipherKey(Base64.decode("2AvVhdsgUs0FSA3SDFAdag=="));
return cookieRememberMeManager;
}
/**
* Realm
* @return
*/
@Bean
public MyRealm myRealm(){
MyRealm myRealm = new MyRealm();
// ,
myRealm.setCredentialsMatcher(hashedCredentialsMatcher());
return myRealm;
}
/**
*
* @param securityManager
* @return
*/
@Bean
public ShiroFilterFactoryBean shirFilter(SecurityManager securityManager) {
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
shiroFilterFactoryBean.setSecurityManager(securityManager);
//
Map filterChainDefinitionMap = new LinkedHashMap();
filterChainDefinitionMap.put("/static/**", "anon"); //anon
filterChainDefinitionMap.put("/logout", "logout"); //shiro ,
// ,
List permissions = permissionService.list();
for (Permission permission : permissions) {
filterChainDefinitionMap.put(permission.getUrl(),"perms["+permission.getSn()+"]");
}
filterChainDefinitionMap.put("/**", "authc");
// , ,
shiroFilterFactoryBean.setLoginUrl("/login");
//
shiroFilterFactoryBean.setSuccessUrl("/index");
// , ,
shiroFilterFactoryBean.setUnauthorizedUrl("/unauthorized");
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
return shiroFilterFactoryBean;
}
}
(4) 도구 클래스 작성
(1)Ajax
/**
* ajax , ,
*
*/
public class AjaxResult {
private Boolean success = true;
private String msg;
private AjaxResult() {
}
/**
* ajax
* @return
*/
public static AjaxResult success(){
return new AjaxResult();
}
/**
* ajax
* @param msg
* @return
*/
public static AjaxResult error(String msg){
AjaxResult ajaxResult = success();;
ajaxResult.setSuccess(false);
ajaxResult.setMsg(msg);
return ajaxResult;
}
public Boolean getSuccess() {
return success;
}
private void setSuccess(Boolean success) {
this.success = success;
}
public String getMsg() {
return msg;
}
private void setMsg(String msg) {
this.msg = msg;
}
}
(2) 세 션 필드 대상 (로그 인 사용자) 액세스 값
public class SessionUtil {
public static final String LOGINSESSION = "loginuser";
//
public static void setSession(Employee employee){//
Subject subject = SecurityUtils.getSubject();//
subject.getSession().setAttribute(LOGINSESSION,employee);
}
//Session
public static Employee getSession(){//
Subject subject = SecurityUtils.getSubject();//
return (Employee) subject.getSession().getAttribute(LOGINSESSION);
}
}
(3) MD5 암호 화
public class MD5Utils {
public static final String SALT = "fm";
public static final int ITERATIONS = 10;
/**
*
* @param source
* @return
*/
public static String encrype(String source){
SimpleHash simpleHash = new SimpleHash("MD5",source,SALT,ITERATIONS);
return simpleHash.toString();
}
public static void main(String[] args) {
System.out.println(encrype("admin"));
}
}
(5) 컨트롤 러 층 로그 인 로그아웃 방법
@Controller
public class LoginController {
/**
*
* @return
*/
@RequestMapping(value = "/login",method = RequestMethod.GET)
public String login(){
Subject subject = SecurityUtils.getSubject();
// rememberMe
if (subject.isRemembered()){
return "main";
//
}else if(subject.isAuthenticated()){
return "main";
}
return "login";
}
/**
*
* @param employee
* @return
*/
@RequestMapping(value = "/login",method = RequestMethod.POST)
@ResponseBody
public AjaxResult login(@RequestBody Employee employee){
//
Subject subject = SecurityUtils.getSubject();
/*Boolean rememberMe = true;*/
// tocken
UsernamePasswordToken token = new UsernamePasswordToken(employee.getUsername(),employee.getPassword(),employee.getRememberMe());
try {
// tocken shiro ----> MyRealm AuthenticationInfo , ,
if(!subject.isAuthenticated()){//
subject.login(token);//
}
//
Employee logiuser = ((Employee) subject.getPrincipal());//
SessionUtil.setSession(logiuser);
return AjaxResult.success();
} catch (UnknownAccountException e) {
e.printStackTrace();
return AjaxResult.error(" ");
}catch (IncorrectCredentialsException e){
e.printStackTrace();
return AjaxResult.error(" ");
} catch (AuthenticationException e) {
e.printStackTrace();
return AjaxResult.error(" , ");
}
}
//
@RequestMapping(value = "/logout")
public String logout(HttpServletRequest request, HttpServletResponse response) {
return "redirect:/logout";
}
}
3. VUE / ElementUI 전단 기반 작성
전단 에 사용 되 는 정적 자원 을 resource / statc 아래 에 놓 습 니 다.
전단 에 사용 할 페이지 는 resource / templates 아래 에 놓 습 니 다.
(1) 비 계 를 설치 하거나 Elementui 를 간단하게 가 져 오 는 js css
(2) 로그 인 인터페이스
Title
new Vue({
el: "#app",
data: {
logining: false,
loginUser: {
username: '',
password: '',
rememberMe:false
},
loginFormRules: {
username: [
{required: true, message: ' ', trigger: 'blur'},
],
password: [
{required: true, message: ' ', trigger: 'blur'},
]
},
checked: false,
},
methods: {
handleLogin(ev) {
var _this = this;
this.$refs.loginForm.validate((valid) => {
if (valid) {
this.logining = true;
//
this.loginUser.rememberMe=this.checked
axios.post("login", this.loginUser)
.then((res) => {
let data = res.data;
if (data.success) {
//
this.logining = false;
//
location.href = "main";
} else {
this.logining = false;
this.$message.error(data.msg, "error");
}
})
} else {
this.$message.error(' ');
return false;
}
});
}
}
});
다른 페이지 는 작성 하면 됩 니 다. 최종 적 으로 제 소스 코드 를 사용 하면 동적 권한 수여 와 인증, remembeMe 기능 이 실 현 됩 니 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Thymeleaf 행 단위로 데이터 게시뷰측 포인트 해설 비고 input type="hidden" 브라우저에는 표시되지 않지만 컨트롤러에 값을 전달할 수 있습니다. name="id"th:value="*{id}" name으로 지정한 값과 Entity 클래스...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.