权限

package com.irhema.shiro;

import at.pollux.thymeleaf.shiro.dialect.ShiroDialect;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.LinkedHashMap;
import java.util.Map;

@Configuration
public class ShiroConfig {
/**
* shiroFilterFactoryBean
* 使用@Bean,将getShiroFilterFactoryBean()方法返回的bean对象装入到spring容器中(放入spring环境中)。
* 好让spring知道我们创建了shiroFilterFactoryBean这样一个对象。否则该方法或该 对象将失效,不起作用
/
@Bean
public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("securityManager")DefaultWebSecurityManager securityManager){
ShiroFilterFactoryBean shiroFilterFactoryBean=new ShiroFilterFactoryBean();
//内置有很多过滤器来进行url的拦截
//设置安全管理器,可通过注解@Qualifier查找securityManager的bean并注入
shiroFilterFactoryBean.setSecurityManager(securityManager);
/
*
* 添加shiro内置过滤器,实现权限相关的拦截器
* 常用的过滤器
* anon 全面开放
* authc 需要认证
* page 使用remember me功能才能访问
* perms 得到该资源权限才能访问 授权拦截器
* role 得到角色权限才能访问 授权拦截器
/
Map<String,String> filterMap=new LinkedHashMap<String, String>();
/
*
* 授权配置
/
filterMap.put("/user/add","perms[user:add]"); /
为添加设置权限拦截--数据库中lmj用户有添加权限--/
shiroFilterFactoryBean.setUnauthorizedUrl("/user/unAuth");
filterMap.put("/user/update","perms[user:update]"); /
为更新设置权限拦截--数据库中admin用户有添加权限--/
//filterMap.put("/user/add","authc");
// filterMap.put("/user/update","authc");
/**
* 认证
/
filterMap.put("/index","anon");
filterMap.put("/user/select","anon");
filterMap.put("/user/login","anon");
filterMap.put("/user/
","authc");
//使用通配符 filterMap.put("/page/
","authc"); 让user下面的所有资源都需要认证后才能放行
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterMap);
/**
* 自定义shirio默认跳转的登陆页面
/
shiroFilterFactoryBean.setLoginUrl("/user/toLogin");
return shiroFilterFactoryBean;
}
/
*
* 创建defaultsecurityManager
* 可通过@Qualifier注解拿到getRealm()方法返回的bean作为参数传入getDefaultWebSecurityManager()方法中
/
@Bean(name="securityManager")
public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("userRealm") UserRealm userRealm){
DefaultWebSecurityManager securityManager=new DefaultWebSecurityManager();
//关联realm
securityManager.setRealm(userRealm);
return securityManager;
}
/
*
* 创建realm
* @Bean注解的含义是让该方法返回的对象注入到spring的环境中,(丢进spring容器里),
* 方便被defaultsecurityManager所调用
*/
@Bean(name="userRealm")
public UserRealm getRealm(){
return new UserRealm();
}

/**
* 配置ShiroDialect,用于Shiro和thymeleaf标签配合使用
* @return
*/
@Bean
public ShiroDialect shiroDialect(){
return new ShiroDialect();
}
}
-----------------------------UserRealm ---------------------
package com.irhema.shiro;

import com.irhema.domain.User;
import com.irhema.service.UserService;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
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.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;

public class UserRealm extends AuthorizingRealm {
@Autowired
UserService userService;
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
UsernamePasswordToken token= (UsernamePasswordToken) authenticationToken;
User user=userService.findByName(token.getUsername());
if (user==null){
return null;
}
//这里传的是user对象,不是"user字符串",这样写会报类型转换错误异常SimpleAuthenticationInfo(“user”,user.getPassword(),"");
return new SimpleAuthenticationInfo(user,user.getPassword(),"");
/**
* 无数据库版本
/
/
String name="lmj";
String password="123";
//将传来的参数转为UsernamePasswordToken
UsernamePasswordToken token= (UsernamePasswordToken) authenticationToken;
if (!token.getUsername().equals(name)){
return null;
}
//返回AuthenticationInfo的子类SimpleAuthenticationInfo即可
(第一个参数是返回给login的信息,它是一个当事人对象Principal,可以填user,方便传到doGetAuthorizationInfo中,
第二个是从数据库取来的密码
// shiro会自动去做密码是否匹配的判断,第三个参数是shiro的名字,我们可以留空,第二个参数一定要是数据库 的密码)
return new SimpleAuthenticationInfo("",password,"");
*/
}

@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
/**
* 使用AuthorizationInfo接口的子类SimpleAuthorizationInfo
* 为用户授予user:add添加的权限
/
SimpleAuthorizationInfo info=new SimpleAuthorizationInfo();
/
*
* 数据库中取出权限字符串
/
Subject subject= SecurityUtils.getSubject();
/
*
* //Principal包含用户的标识和用户的所属角色的对象---专业术语叫--当事人,委托人 ,拿到当事人对象
* 它是认证是传过来的,故需要将原来的doGetAuthorizationInfo()方法中的
* return new SimpleAuthenticationInfo("",user.getPassword(),"");
*
* 更改为:
* return new SimpleAuthenticationInfo("user",user.getPassword(),"");
*/
User user= (User) subject.getPrincipal();
User dbUser=userService.findById(user.getId());
info.addStringPermission(dbUser.getPerms());
return info;
}
}
-----------------index

Title

登录



4.0.0

org.springframework.boot
spring-boot-starter-parent
2.1.6.RELEASE


com
irhema
0.0.1-SNAPSHOT
irhema
Demo project for Spring Boot


<java.version>1.8</java.version>



org.springframework.boot
spring-boot-starter-thymeleaf


org.springframework.boot
spring-boot-starter-web


org.springframework.boot
spring-boot-devtools
runtime
true


org.projectlombok
lombok
true


org.springframework.boot
spring-boot-starter-test
test


org.apache.shiro
shiro-spring
1.3.2




com.alibaba
druid
1.1.17



mysql
mysql-connector-java
8.0.16



org.mybatis.spring.boot
mybatis-spring-boot-starter
2.0.0




com.github.theborakompanioni
thymeleaf-extras-shiro
2.0.0




org.springframework.boot
spring-boot-maven-plugin





src/main/java

/*.java



src/main/resources

/.



package com.irhema.controller;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;

import java.util.Map;

@Controller
@RequestMapping("/user")
public class UserController {
//因为我们使用了springmvc的全局拦截功能,所以使用超链接跳转就不行了。我们需要写controller。
//让它经过controller来进行资源的访问。相当于controller里配置的资源访问路径是springmvc认为合法的
//允许放行的资源路径
@RequestMapping("/add")
public String add(){
return "add";
}
@RequestMapping("/update")
public String update(){
return "update";
}
@RequestMapping("/toLogin")
public String tologin(){
return "login";
}
@RequestMapping("/select")
public String select(Map<String,Object> map){
map.put("msg","hello");
return "select";
}
@RequestMapping("/login")
public String login(String username, String password, Map<String,Object> map){
map.put("msg","登陆成功:"+" "+username+" "+password);
/**
*使用shiro编写认证操作
*/
// todo 获取subject(通过securityUtil拿到subject用户主题)
Subject subject= SecurityUtils.getSubject();

// todo 封装用户数据(将用户名,密码装进usernamepasstoken对象里面)
UsernamePasswordToken token=new UsernamePasswordToken(username,password);
try{
/**
* 这里shiro会将login的处理流程交给UserRealm
* 我们在userRealm的doGetAuthenticationInfo和doGetAuthorizationInfo里写我们的业务逻辑就可以了
* 只要执行了subject.login(token);方法,它就一定会来到认证逻辑这里 及上面的两个方法
*/
subject.login(token);
return "index";
//无异常,则说明登陆成功
}catch (UnknownAccountException e){
// e.printStackTrace();
//登陆失败,用户名不存在
map.put("msg","用户名不存在");
//不加redirect重定向,程序会认为这是一个页面,我们需要的它是一个请求路径
System.out.println("用户名不存在");
return "index";
}catch (IncorrectCredentialsException e){
map.put("msg","密码错误");
System.out.println("密码错误");
return "index";
}catch (Exception e){
System.out.println("用户名或密码为空");
return null;
}
}
@RequestMapping("/unAuth")
public String unAuth(Map<String,Object> map){
map.put("msg","请去授权");
return "unAuth";
}
}

posted @ 2020-11-11 19:18  brc  阅读(110)  评论(0)    收藏  举报