安全框架,简单说是对访问权限进行控制,应用的安全性包括用户认证(Authentication)和用户授权(Authorization)两个部分。
用户认证指的是验证某个用户是否为系统中的合法主体,也就是说用户能否访问该系统。
用户认证一般要求用户提供用户名和密码,系统通过校验用户名和密码来完成认证过程。
用户授权指的是验证某个用户是否有权限执行某个操作。在一个系统中,不同用户所具有的权限是不同的。比如对一个文件来说,有的用户只能进行读取,而有的用户可以进行修改。
一般来说,系统会为不同的用户分配不同的角色,而每个角色则对应一系列的权限。
config文件下创建XxxConfig 继承 WebSecurityConfigurerAdapter 类 在方法上加上@EnableWebSecurity
开启Security
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
//链式编程
@Override
protected void configure(HttpSecurity http) throws Exception {
//首页所有人可以访问,功能页只要对应有权限的人才可以访问
http.authorizeRequests()
.antMatchers("/").permitAll()
.antMatchers("/level1/**").hasRole("vip1")
.antMatchers("/level2/**").hasRole("vip2")
.antMatchers("/level3/**").hasRole("vip3");
http.formLogin().loginPage("/toLogin");
//注销功能
http.csrf().disable();
http.logout().logoutSuccessUrl("/");
//记住我
http.rememberMe();
}
//认证
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication().passwordEncoder(new BCryptPasswordEncoder())
.withUser("xm").password(new BCryptPasswordEncoder().encode("123456")).roles("vip2","vip3")
.and()
.withUser("root").password(new BCryptPasswordEncoder().encode("123456")).roles("vip1","vip2","vip3")
.and()
.withUser("guest").password(new BCryptPasswordEncoder().encode("123456")).roles("vip1");
}
}
<dependency>
<groupId>org.apache.shirogroupId>
<artifactId>shiro-coreartifactId>
<version>1.5.2version>
dependency>
<dependency>
<groupId>org.slf4jgroupId>
<artifactId>jcl-over-slf4jartifactId>
<version>1.7.21version>
dependency>
<dependency>
<groupId>org.slf4jgroupId>
<artifactId>slf4j-log4j12artifactId>
<version>1.7.21version>
dependency>
<dependency>
<groupId>log4jgroupId>
<artifactId>log4jartifactId>
<version>1.2.17version>
dependency>
# Global logging configuration 开发时候建议使用 debug
log4j.rootLogger=DEBUG, stdout
# Console output...
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n
需要下载ini插件
在resource下创建shiro.ini
[users]
# user 'root' with password 'secret' and the 'admin' role
root = secret, admin
# user 'guest' with the password 'guest' and the 'guest' role
guest = guest, guest
# user 'presidentskroob' with password '12345' ("That's the same combination on
# my luggage!!!" ;)), and role 'president'
presidentskroob = 12345, president
# user 'darkhelmet' with password 'ludicrousspeed' and roles 'darklord' and 'schwartz'
darkhelmet = ludicrousspeed, darklord, schwartz
# user 'lonestarr' with password 'vespa' and roles 'goodguy' and 'schwartz'
lonestarr = vespa, goodguy, schwartz
# -----------------------------------------------------------------------------
# Roles with assigned permissions
#
# Each line conforms to the format defined in the
# org.apache.shiro.realm.text.TextConfigurationRealm#setRoleDefinitions JavaDoc
# -----------------------------------------------------------------------------
[roles]
# 'admin' role has all permissions, indicated by the wildcard '*'
admin = *
# The 'schwartz' role can do anything (*) with any lightsaber:
schwartz = lightsaber:*
# The 'goodguy' role is allowed to 'drive' (action) the winnebago (type) with
# license plate 'eagle5' (instance specific id)
goodguy = winnebago:drive:eagle5
Quickstart.java
//得到当前对象的用户对象 Subject
Subject currentUser = SecurityUtils.getSubject();
//通过当前用户获得shiro Session
Session session = currentUser.getSession();
//判断当前的用户是否被认证
if (!currentUser.isAuthenticated()) {
}
//获得当前用户的认证
currentUser.getPrincipal()
//是否拥有这个角色
currentUser.hasRole("schwartz")
//获得当前用户的权限
currentUser.isPermitted("lightsaber:wield")
//all done - log out!注销
currentUser.logout();
Subject 用户
SecurityManager 管理所有用户
Realm 连接数据
整合
<dependency>
<groupId>org.apache.shirogroupId>
<artifactId>shiro-springartifactId>
<version>1.5.1version>
dependency>
创建config.UserRealm 和 config.ShiroConfig
UserRealm
自定义的realm extends AuthorizingRealm
public class UserRealm extends AuthorizingRealm {
//授权
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
System.out.println("执行了授权");
return null;
}
//认证
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
System.out.println("执行了认证");
return null;
}
}
ShiroConfig
@Configuration
public class ShiroConfig {
//ShiroFilterFactoryBean 3
@Bean
public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("getDefaultWebSecurityManager") DefaultWebSecurityManager defaultWebSecurityManager){
ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();
//设置安全管理器
bean.setSecurityManager(defaultWebSecurityManager);
return bean;
}
//DefaultWebSecurityManager 2
@Bean
public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("userRealm") UserRealm userRealm){
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
//关联UserRealm
securityManager.setRealm(userRealm);
return securityManager;
}
//创建realm对象,需要自定义 1
@Bean
public UserRealm userRealm(){
return new UserRealm();
}
}
添加Shiro的内置过滤器
@Bean
public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("getDefaultWebSecurityManager") DefaultWebSecurityManager defaultWebSecurityManager){
ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();
//设置安全管理器
bean.setSecurityManager(defaultWebSecurityManager);
//添加shiro的内置过滤器
/*
anon : 无需认证就可以访问
authc: 必须认证了才能访问
user: 必须拥有记住我功能才能用
perms: 拥有对某个资源的权限才能访问
role: 拥有某个角色权限才能访问
* */
Map<String, String> filterMap = new LinkedHashMap<>();
//filterMap.put("/user/add", "authc");
//filterMap.put("/user/update", "authc");
filterMap.put("/user/*", "authc");
bean.setFilterChainDefinitionMap(filterMap);
//设置登录的请求
bean.setLoginUrl("/toLogin");
return bean;
}
在UserRealm的AuthenticationInfo 方法中
//认证
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
System.out.println("执行了认证");
//用户 密码 数据库取 token 令牌
UsernamePasswordToken userToken = (UsernamePasswordToken) token;
User user = userService.queryUserByName(userToken.getUsername());
if (user == null){
return null;
}
//可以加密 :MD5 MD5盐值加密
//密码认证 不需要处理 shiro 处理 加密了
return new SimpleAuthenticationInfo("", user.getPwd(), "");
}
连接数据库 整合MyBatis
从前端接收用户名,密码并判断
@RequestMapping("/login")
public String login(String username,String password,Model model){
//获取当前用户
Subject subject = SecurityUtils.getSubject();
//封装当前用户的信息
UsernamePasswordToken token = new UsernamePasswordToken(username, password);
try {
//执行登录的方法 没有异常则OK
subject.login(token);
return "index";
}catch (UnknownAccountException e){
model.addAttribute("msg","用户名错误");
return "login";
}catch (IncorrectCredentialsException e){
model.addAttribute("msg","密码错误");
return "login";
}
}
在ShiroConfig 中getShiroFilterFactoryBean方法
//授权 必须是user才有add权限
filterMap.put("/user/add", "perms[user:add]");
没有权限会报401错误
//未授权页面
bean.setUnauthorizedUrl("/noauth");
普通的Thread .sleep(3000); 浏览器会转3s 没有页面信息,非常影响用户体验。
而加入注解就可以解决没有页面信息的问题
这样 浏览器就会即时返回页面信息 3s后后台处理信息
发送邮件
导入依赖
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-mailartifactId>
dependency>
@Autowired
JavaMailSenderImpl mailSender;
@Test
void contextLoads() {
//简单的邮件
SimpleMailMessage mailMessage = new SimpleMailMessage();//2.需要这个参数就new这个参数
mailMessage.setSubject("你好!");//主题
mailMessage.setText("xxxxx");//正文
mailMessage.setTo("[email protected]");//发给谁
mailMessage.setFrom("[email protected]");//谁发的
mailSender.send(mailMessage);// 1.方法
}
@Test
void contextLoad2() throws MessagingException {
MimeMessage mimeMessage = mailSender.createMimeMessage();//2.new 这个参数
//正文
MimeMessageHelper helper = new MimeMessageHelper(mimeMessage,true);
helper.setSubject("XMXMXMXMXM");//主题
helper.setText("谢谢谢谢!
",true);//正文
//附件
helper.addAttachment("1.png", new File("C:\\Users\\Administrator\\Desktop\\新建文件夹\\images\\1.png"));
helper.setTo("[email protected]");//发给谁
helper.setFrom("[email protected]");//谁发
mailSender.send(mimeMessage);//1.方法
}
在特定的时间执行任务
cron = “0 * * * * 0-7” 秒 分 时 日 月 每周(0 7都表示星期天) 每60秒执行一次方法
下一篇学习
SpringBoot详解(六) 从入门到入土 (shiro 邮件)