springboot整合shiro安全框架

147 阅读1分钟

springboot整合shiro安全框架

1.创建springboot工程

image.png

2.引入依赖

<dependencies>
<!--        my的依赖-->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.4.2</version>
        </dependency>
<!--        thymeleaf依赖-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
<!--        web依赖-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
<!--数据路连接-->
        <dependency>
            <groupId>com.mysql</groupId>
            <artifactId>mysql-connector-j</artifactId>
            <scope>runtime</scope>
        </dependency>
<!--        lombok-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <!--shiro和springboot整合的依赖-->
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-spring-boot-starter</artifactId>
            <version>1.7.0</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

3.application配置文件

#连接数据库
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql:///shiro?serverTimezone=Asia/Shanghai
spring.datasource.username=root
spring.datasource.password=123456

#日志
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl

mybatis-plus.mapper-locations=classpath:/mapper/*.xml

#thymeleaf的视图解析器
spring.thymeleaf.prefix=classpath:/templates/
spring.thymeleaf.suffix=.html


#shiro配置文件需要的值|密码加密器
shiro.hashAlgorithmName=MD5
shiro.hashIterations=1024

4.编写实体类和dao类

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Permission {
   @TableId(type = IdType.AUTO) //注解列名如果不是id ,则需要使用TableId注解
   private Integer perid;
   private String pername;
   private String percode;
}
@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {
    //自动递增
    @TableId(type = IdType.AUTO)     //注解列名如果不是id ,则需要使用TableId注解
    Integer userid;
    String username;
    String userpwd;
    String sex;
    String address;
    String salt;
}

image.png

image.png

(5)编写UserService

@Override
public User findUserByUsername(String username) {
        QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
        userQueryWrapper.eq("username",username);
        User user = userDao.selectOne(userQueryWrapper);
        return user;
}

(6)编写realm

public class MyRealm extends AuthorizingRealm {

    @Autowired
    private UserService userService;
        //授权
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {

        return null;
    }

    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
       //获取登录账号
        final String username = authenticationToken.getPrincipal().toString();
        //根据账号获取用户信息
        User user =  userService.findUserByUsername(username);
        if(user!=null){
            final ByteSource salt = ByteSource.Util.bytes(user.getSalt());
            SimpleAuthenticationInfo info= new SimpleAuthenticationInfo(user,user.getUserpwd(),salt,this.getName());
            return info;
        }
        return null;
    }
}

(7)编写LoginController

@Controller
//将后端返回的数据转为json格式
//esponseBody
public class LoginController {

    @PostMapping("/login")
    public Stringn(LoginVo loginVo){
        final Subject subject = SecurityUtils.getSubject();
        UsernamePasswordToken token = new UsernamePasswordToken(loginVo.getUsername(),loginVo.getPassword());
        try{
            subject.login(token);
            //登录成功返回200
            return "success;
        }catch (Exception e){
            e.printStackTrace();
            return null;
        }
    }

    //未登陆时跳转的路径
    @GetMapping("/unlogin")
    @ResponseBody
    public Result unlogin(){
        return new Result(401,"未登录",null);
    }
}

(8)编写shiro配置类


@Configuration//配置类
public class ShiroConfig {

    //获得配置文件中的值
    @Value("${shiro.hashIterations}")
    private int hashIterations;

    @Value("${shiro.hashAlgorithmName}")
    private String hashAlgorithmName;

    @Bean
    public DefaultWebSecurityManager securityManager(){

        final DefaultWebSecurityManager manager = new DefaultWebSecurityManager();
        manager.setRealm(myRealm());
        return manager;

    }
    @Bean
    public MyRealm myRealm(){
        final MyRealm myRealm = new MyRealm();
        myRealm.setCredentialsMatcher(credentialsMatcher());
        return myRealm;
    }

    @Bean
    public HashedCredentialsMatcher credentialsMatcher(){
        final HashedCredentialsMatcher matcher = new HashedCredentialsMatcher();
        //加密使用加密器
        matcher.setHashAlgorithmName(hashAlgorithmName);
        //密码加密次数
        matcher.setHashIterations(hashIterations);
        return matcher;
    }
    
    @Bean(name = "shiroFilter")
    public ShiroFilterFactoryBean factoryBean(){
        final ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        shiroFilterFactoryBean.setSecurityManager(securityManager());
        shiroFilterFactoryBean.setLoginUrl("/login.html");
        //设置过滤规则
        final HashMap<String, String> map = new HashMap<>();
        map.put("/login","anon");
        map.put("/**","authc");
        shiroFilterFactoryBean.setFilterChainDefinitionMap(map);
        return shiroFilterFactoryBean;
    }
    //注册过滤器
    @Bean
    public FilterRegistrationBean<Filter> filterRegistrationBean(){
        final FilterRegistrationBean<Filter> filterFilterRegistrationBean = new FilterRegistrationBean<>();
        filterFilterRegistrationBean.setFilter(new DelegatingFilterProxy());
        filterFilterRegistrationBean.setName("shiroFilter");
        filterFilterRegistrationBean.addUrlPatterns("/*");
        return filterFilterRegistrationBean;
    }

}

(9)编写登录界面

image.png

(10)编写登录成功界面

image.png

springboot整合shiro--授权【权限】

(1)修改Myrealm

@Autowired
private PermissionService permissionService;
    //授权
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
    //获取当前登录者的账号|对象
    User user = (User) principalCollection.getPrimaryPrincipal();
    //调用userSerice中的方法--根据id
    List<String> permission = permissionService.findPermissionByUserId(user.getUserid());
    if(permission.size()!=0){
        SimpleAuthorizationInfo info =new SimpleAuthorizationInfo();
        System.out.println("--------------");
        info.addStringPermissions(permission);
        return info;
    }
    return null;
}

(2)编写PermissionService

@Service
public class PermissionServiceImpl implements PermissionService {

    @Autowired
    private PermissionDao permissionDao;


    @Override
    public List<String> findPermissionByUserId(Integer userid) {

        final List<Permission> permission = permissionDao.findPermissionByUserId(userid);
        final List<String> collect = permission.stream().map(Permission::getPercode).collect(Collectors.toList());
        return collect;
    }
}

(3Permissiondao和映射文件

image.png

(4)浏览器观察

发现所有的权限都显示,我们的前端页面shiro标签并没有生效

image.png

(5)shrio和thymeleaf集成的扩展依赖

<!--shrio和thymeleaf集成的扩展依赖,为了能在页面上使用xsln:shrio的标签 -->
<dependency>
    <groupId>com.github.theborakompanioni</groupId>
    <artifactId>thymeleaf-extras-shiro</artifactId>
    <version>2.0.0</version>
</dependency>

(6)修改shiro配置类

/**
 * 这里是为了能在html页面引用shiro标签,
 */
@Bean(name = "shiroDialect")
public ShiroDialect shiroDialect() {
    return new ShiroDialect();
}

后面就是将前后端不分离改为前后端分离,还整合了redis,避免多次权限查询:仓库地址:gitee.com/junjie-chen…